home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / modes / eiffel3.el.z / eiffel3.el
Encoding:
Text File  |  1998-05-21  |  80.0 KB  |  2,261 lines

  1. ;;; $Id: eiffel3.el,v 1.85 1996/07/06 01:27:09 tynor Exp $
  2. ;;;--------------------------------------------------------------------------
  3. ;;; TowerEiffel -- Copyright (c) 1993-1996 Tower Technology Corporation. 
  4. ;;; All Rights Reserved.
  5. ;;; 
  6. ;;; Use, duplication, or disclosure is subject to restrictions as set forth 
  7. ;;; in subdivision (c)(1)(ii) of the Rights in Technical Data and Computer 
  8. ;;; Software clause at DFARS 252.227-7013.
  9. ;;;
  10. ;;; This file is made available for use and distribution under the same terms 
  11. ;;; as GNU Emacs. Such availability of this elisp file should not be construed 
  12. ;;; as granting such availability to the rest of TowerEiffel.
  13. ;;;--------------------------------------------------------------------------
  14. ;;; Portions of the file, as indicated below, were derived from "eiffel.el"
  15. ;;; (developed by Stephen Omohundro, ISE and Bob Weiner) and "eif-mult-fmt.el"
  16. ;;; (developed by Bob Weiner):
  17. ;;;   eiffel.el and eif-mult-fmt.el are Copyright (C) 1989, 1990 
  18. ;;;   Free Software Foundation, Inc. and Bob Weiner
  19. ;;;   Available for use and distribution under the same terms as GNU Emacs.
  20.  
  21. ;;; Synched up with: Not in FSF.
  22.  
  23. ;;;--------------------------------------------------------------------------
  24. ;;; Adapted the file for the XEmacs 19.12 distribution. -- jasa (1995/03/11)
  25. ;;;--------------------------------------------------------------------------
  26. ;;;
  27. ;;;  EIFFEL3  : GNU Emacs mode for Eiffel Version 3
  28. ;;;
  29. ;;;  INSTALLATION
  30. ;;;    To install, simply copy this file into a directory in your
  31. ;;;    load-path and add the following two commands in your .emacs file:
  32. ;;;
  33. ;;;        (setq auto-mode-alist (cons '("\\.e$" . eiffel-mode) 
  34. ;;;                              auto-mode-alist))
  35. ;;;        (autoload 'eiffel-mode "eiffel3" "Mode for Eiffel programs" t)
  36. ;;;
  37. ;;;    TowerEiffel users should do the following instead: See the file
  38. ;;;    dot-emacs that comes with the TowerEiffel distribution for a sample
  39. ;;;    ".emacs" file. If all Tower elisp files are already in your
  40. ;;;    load-path, then simply add the following line to your .emacs file: 
  41. ;;;
  42. ;;;        (load "tinstall")
  43. ;;;
  44. ;;;  TOWER EIFFEL
  45. ;;;    TowerEiffel provides additional Emacs support for Eiffel
  46. ;;;    programming that integrates Emacs with Tower's Eiffel compiler,
  47. ;;;    documentation, and browsing tools. For more information on
  48. ;;;    these tools and their Emacs interface contact:
  49. ;;;
  50. ;;;        Tower Technology Corporation
  51. ;;;        1501 Koenig Dr.
  52. ;;;        Austin TX, 78756
  53. ;;;  
  54. ;;;         tower@twr.com (to reach a human being)
  55. ;;;         info@twr.com  (automated file server)
  56. ;;;         (512)452-1721 (FAX)
  57. ;;;         (512)452-9455 (phone)
  58. ;;;
  59. ;;;  SUPPORT
  60. ;;;    Please send bug reports, fixes or enhancements to:
  61. ;;;       elisp@atlanta.twr.com
  62. ;;;
  63. ;;;  COMPATIBILITY:
  64. ;;;    This file has been tested with XEmacs 19.11.  Syntax highlighting is
  65. ;;;    primarily supported with font-lock.el.
  66. ;;;
  67. ;;;  COMMANDS
  68. ;;;    eif-backward-sexp
  69. ;;;    eif-feature-quote
  70. ;;;    eif-forward-sexp
  71. ;;;    eif-goto-matching-line
  72. ;;;    eif-indent-region
  73. ;;;    eif-indent-construct
  74. ;;;    eif-indent-line
  75. ;;;    eif-newline
  76. ;;;    eiffel-mode
  77. ;;;
  78. ;;;  PUBLIC VARIABLES
  79. ;;;    eif-body-comment-indent
  80. ;;;    eif-check-keyword-indent
  81. ;;;    eif-class-level-comment-indent
  82. ;;;    eif-class-level-kw-indent
  83. ;;;    eif-extra-body-comment-indent
  84. ;;;    eif-extra-check-keyword-indent
  85. ;;;    eif-extra-class-level-comment-indent
  86. ;;;    eif-extra-class-level-kw-indent
  87. ;;;    eif-extra-feature-level-comment-indent
  88. ;;;    eif-extra-feature-level-indent
  89. ;;;    eif-extra-feature-level-kw-indent
  90. ;;;    eif-extra-inherit-level-kw-indent
  91. ;;;    eif-extra-then-indent
  92. ;;;    eif-feature-level-comment-indent
  93. ;;;    eif-feature-level-indent
  94. ;;;    eif-feature-level-kw-indent
  95. ;;;    eif-indent-increment
  96. ;;;    eif-inherit-level-kw-indent
  97. ;;;    eif-rescue-keyword-indent
  98. ;;;    eif-then-indent
  99. ;;;    eiffel-mode-abbrev-table
  100. ;;;    eiffel-mode-hook
  101. ;;;    eiffel-mode-map
  102. ;;;    eiffel-mode-syntax-table
  103. ;;;
  104. ;;;  PUBLIC FUNCTIONS
  105. ;;;    None.
  106. ;;;
  107. ;;;  HISTORY
  108. ;;;    Fred Hart    - Jul 31, 1992: Created.
  109.  
  110. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  111. ;;;              Indentation Amount Variables.                   ;;;
  112. ;;;                                                              ;;;
  113. ;;; The default values correspond to style used in ``Eiffel: The ;;;
  114. ;;; Language''.  Note: for TowerEiffel users the values below    ;;;
  115. ;;; will be superceded by the values in either tcustom.el or     ;;;
  116. ;;; ~/.tcustom.el if  it is present.                             ;;;
  117. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  118.  
  119. (defvar eif-indent-increment                   3 
  120.   "Default indentation interval (in spaces)")
  121.  
  122. (defvar eif-class-level-kw-indent        0 
  123.   "Indentation amount for Class level keywords (in number of
  124. eif-indent-increments) (see eif-class-level-keywords variable).")
  125. (defvar eif-extra-class-level-kw-indent        0 
  126.   "Number of SPACES to add to eif-class-level-kw-indent to get the
  127. actual indentation of a class level keyword. Can be negative.")
  128.  
  129. (defvar eif-class-level-comment-indent   0 
  130.   "Indentation of comments at the beginning of the class (in number of
  131. eif-indent-increments)")
  132. (defvar eif-extra-class-level-comment-indent   0 
  133.   "Number of SPACES to add to eif-class-level-comment-indent to get the
  134. actual indentation of a class level comment. Can be negative.")
  135.  
  136. (defvar eif-inherit-level-kw-indent      2 
  137.   "Indentation of keywords falling under the Inherit clause (in number of
  138. eif-indent-increments) (see eif-inherit-level-keywords variable.")
  139. (defvar eif-extra-inherit-level-kw-indent      0 
  140.   "Number of SPACES to add to eif-inherit-level-kw-indent to get the
  141. actual indentation of an inherit level keyword. Can be negative.")
  142.  
  143. (defvar eif-feature-level-indent         1 
  144.   "Indentation amount of features. (in number of eif-indent-increments)")
  145. (defvar eif-extra-feature-level-indent         0 
  146.   "Number of SPACES to add to eif-feature-level-indent to get the
  147. actual indentation of a feature. Can be negative.")
  148.  
  149. (defvar eif-feature-level-kw-indent      2 
  150.   "Indentation of keywords belonging to individual features. (in number of
  151. eif-indent-increments) (see eif-feature-level-keywords variable)")
  152. (defvar eif-extra-feature-level-kw-indent      0 
  153.   "Number of SPACES to add to eif-feature-level-kw-indent to get the
  154. actual indentation of a feature level keyword. Can be negative.")
  155.  
  156. (defvar eif-feature-level-comment-indent 3 
  157.   "Indentation of comments at the beginning of a feature. (in number of
  158. eif-indent-increments)")
  159. (defvar eif-extra-feature-level-comment-indent 0 
  160.   "Number of SPACES to add to eif-feature-level-comment-indent to get the
  161. actual indentation of a feature level comment. Can be negative.")
  162.  
  163. (defvar eif-body-comment-indent 0 
  164.   "Indentation of comments in the body of a routine. (in number of
  165. eif-indent-increments)")
  166. (defvar eif-extra-body-comment-indent 0 
  167.   "Number of SPACES to add to eif-body-comment-indent to get the
  168. actual indentation of a routine body comment. Can be negative.")
  169.  
  170. (defvar eif-check-keyword-indent         0
  171.   "Extra indentation for the check clause as described in ETL. (in number of
  172. eif-indent-increments). Default is 0, which is different than in ETL's 1.")
  173. (defvar eif-extra-check-keyword-indent         0
  174.   "Number of SPACES to add to eif-check-keyword-indent to get the
  175. actual indentation of a check keyword. Can be negative.")
  176.  
  177. (defvar eif-rescue-keyword-indent         -1
  178.   "Extra indentation for the rescue clause as described in ETL. (in number of
  179. eif-indent-increments). Default is -1.")
  180. (defvar eif-extra-rescue-keyword-indent         0
  181.   "Number of SPACES to add to eif-rescue-keyword-indent to get the
  182. actual indentation of a rescue keyword. Can be negative.")
  183.  
  184. (defvar eif-then-indent                  0
  185.   "Indentation for a `then' appearing on a line by itself rather 
  186. than on the same line as an `if'. (in number of eif-indent-increments)")
  187. (defvar eif-extra-then-indent                  1
  188.   "Number of SPACES to add to eif-then-indent to get the
  189. actual indentation of a `then' appearing on a line by itself. Can be 
  190. negative.")
  191.  
  192. (defvar eif-continuation-indent                1
  193.   "Extra indentation for a continued statement line. (in number of eif-indent-increments)")
  194. (defvar eif-extra-continuation-indent          0
  195.   "Number of SPACES to add to eif-continuation-indent to get the
  196. actual indentation of a continued statement line. Can be 
  197. negative.")
  198.  
  199. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  200. ;;;           font-lock, lhilit, and hilit19 support             ;;;
  201. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  202.  
  203. ;; The value for a font variable must either be a string
  204. ;; specifying a valid font, the symbol 'default meaning the
  205. ;; default font, or the symbol 'context meaning the font of the
  206. ;; surrounding text. 
  207. ;;
  208. ;; Simlarly, the value for a color variable must either be a string
  209. ;; specifying a valid color, the symbol 'default meaning the
  210. ;; default foreground color, or the symbol 'context meaning the
  211. ;; foregound color of the  surrounding text. 
  212.  
  213. (if (or (featurep 'font-lock) (featurep 'lhilit) (featurep 'hilit19)) (progn
  214.  
  215. (cond ((eq window-system 'pm)
  216.        (defvar eif-comment-font 'default
  217.      "The font in which to display comments in Eiffel and Ace files (either a font name string or 'default or 'context)")
  218.        (defvar eif-comment-color "firebrick" 
  219.      "Color of comments in Eiffel and Ace files (either a color name string or 'default or 'context)")
  220.        
  221.        (defvar eif-hidden-comment-font 'default
  222.      "The font in which to display hidden comments in Eiffel and Ace files (either a font name string or 'default or 'context)")
  223.        (defvar eif-hidden-comment-color "os2darkgreen" 
  224.      "Color of hidden comments in Eiffel and Ace files (either a color name string or 'default or 'context)")
  225.        
  226.        (defvar eif-major-keyword-font 'default
  227.      "The font in which to display major keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  228.        (defvar eif-major-keyword-color 'default
  229.      "Color of major keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  230.        
  231.        (defvar eif-assertion-keyword-font 'default
  232.      "The font in which to display assertion keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  233.        (defvar eif-assertion-keyword-color "os2darkblue"
  234.      "Color of assertion keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  235.        
  236.        (defvar eif-minor-keyword-font 'default
  237.      "The font in which to display minor keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  238.        (defvar eif-minor-keyword-color 'default
  239.      "Color of minor-keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  240.        
  241.        (defvar eif-string-font 'default
  242.      "The font in which to display literal strings in Eiffel and Ace files (either a font name string or 'default or 'context)")
  243.        (defvar eif-string-color "os2darkcyan"
  244.      "Color of literal strings in Eiffel and Ace files (either a color name string or 'default or 'context)")
  245.        
  246.        (defvar eif-quoted-feature-font 'default
  247.      "The font in which to display features names enclosed in `'s in Eiffel and Ace file comments (either a font name string or 'default or 'context)")
  248.        (defvar eif-quoted-feature-color 'context 
  249.      "Color of features names enclosed in `'s in Eiffel and Ace file comments (either a color name string or 'default or 'context)")
  250.        )
  251.  
  252.       ((eq window-system 'ns)
  253.        (defvar eif-comment-font 'default
  254.      "The font in which to display comments in Eiffel and Ace files (either a font name string or 'default or 'context)")
  255.        (defvar eif-comment-color "red3" 
  256.      "Color of comments in Eiffel and Ace files (either a color name string or 'default or 'context)")
  257.        
  258.        (defvar eif-hidden-comment-font 'default
  259.      "The font in which to display hidden comments in Eiffel and Ace files (either a font name string or 'default or 'context)")
  260.        (defvar eif-hidden-comment-color "ForestGreen" 
  261.      "Color of hidden comments in Eiffel and Ace files (either a color name string or 'default or 'context)")
  262.        
  263.        (defvar eif-major-keyword-font "Courier-Bold"
  264.      "The font in which to display major keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  265.        (defvar eif-major-keyword-color 'default
  266.      "Color of major keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  267.        
  268.        (defvar eif-assertion-keyword-font "Courier-Bold"
  269.      "The font in which to display assertion keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  270.        (defvar eif-assertion-keyword-color "slate blue"
  271.      "Color of assertion keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  272.        
  273.        (defvar eif-minor-keyword-font "Courier-Bold"
  274.      "The font in which to display minor keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  275.        (defvar eif-minor-keyword-color 'default
  276.      "Color of minor-keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  277.        
  278.        (defvar eif-string-font 'default 
  279.      "The font in which to display literal strings in Eiffel and Ace files (either a font name string or 'default or 'context)")
  280.        (defvar eif-string-color "sienna"
  281.      "Color of literal strings in Eiffel and Ace files (either a color name string or 'default or 'context)")
  282.        
  283.        (defvar eif-quoted-feature-font 'default
  284.      "The font in which to display features names enclosed in `'s in Eiffel and Ace file comments (either a font name string or 'default or 'context)")
  285.        (defvar eif-quoted-feature-color 'context 
  286.      "Color of features names enclosed in `'s in Eiffel and Ace file comments (either a color name string or 'default or 'context)")
  287.        )
  288.  
  289.       ((eq window-system 'x)
  290.        (defvar eif-comment-font 'default
  291.      "The font in which to display comments in Eiffel and Ace files (either a font name string or 'default or 'context)")
  292.        (defvar eif-comment-color "red3" 
  293.      "Color of comments in Eiffel and Ace files (either a color name string or 'default or 'context)")
  294.        
  295.        (defvar eif-hidden-comment-font 'default
  296.      "The font in which to display hidden comments in Eiffel and Ace files (either a font name string or 'default or 'context)")
  297.        (defvar eif-hidden-comment-color "ForestGreen" 
  298.      "Color of hidden comments in Eiffel and Ace files (either a color name string or 'default or 'context)")
  299.        
  300.        (defvar eif-major-keyword-font "-*-fixed-bold-*-*-*-*-100-*-*-*-*-*-*"
  301.      "The font in which to display major keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  302.        (defvar eif-major-keyword-color 'default
  303.      "Color of major keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  304.        
  305.        (defvar eif-assertion-keyword-font "-*-fixed-bold-*-*-*-*-100-*-*-*-*-*-*"
  306.      "The font in which to display assertion keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  307.        (defvar eif-assertion-keyword-color "slate blue"
  308.      "Color of assertion keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  309.        
  310.        (defvar eif-minor-keyword-font "-*-fixed-bold-*-*-*-*-100-*-*-*-*-*-*"
  311.      "The font in which to display minor keywords in Eiffel and Ace files (either a font name string or 'default or 'context)")
  312.        (defvar eif-minor-keyword-color 'default
  313.      "Color of minor-keywords in Eiffel and Ace files (either a color name string or 'default or 'context)")
  314.        
  315.        (defvar eif-string-font 'default 
  316.      "The font in which to display literal strings in Eiffel and Ace files (either a font name string or 'default or 'context)")
  317.        (defvar eif-string-color "sienna"
  318.      "Color of literal strings in Eiffel and Ace files (either a color name string or 'default or 'context)")
  319.        
  320.        (defvar eif-quoted-feature-font "-*-times-medium-i-*-*-*-120-*-*-*-*-*-*"
  321.      "The font in which to display features names enclosed in `'s in Eiffel and Ace file comments (either a font name string or 'default or 'context)")
  322.        (defvar eif-quoted-feature-color 'context 
  323.      "Color of features names enclosed in `'s in Eiffel and Ace file comments (either a color name string or 'default or 'context)")
  324.        )
  325.       ) 
  326.  
  327. (defvar default-foreground-color 'default
  328.   "Default text color in Eiffel and Ace files (either a color name string or 'default or 'context)")
  329.  
  330. (defvar disable-color nil "Should hilighting not use colors")
  331.  
  332.  
  333. (defun eif-set-foreground (face color)
  334.   "Set the FACE's foreground color to COLOR if COLOR is a string, to the default foreground color if COLOR is 'default, or to the color of the surrounding text if COLOR is 'context"
  335.   (cond ((stringp color)
  336.      ;; If the specified color is not useable, use 'default:
  337.      (condition-case error
  338.          (set-face-foreground face color)
  339.            (error
  340.         (progn
  341.           (message "eif-set-foreground failed for face %s and color %s. Setting to 'default" face color)
  342.           (eif-set-foreground face 'default)))
  343.        )
  344.      )
  345.     ((eq color 'context)
  346.      (remove-face-property face 'foreground)
  347.      )
  348.     ((eq color 'default)
  349.          (set-face-foreground face (face-foreground 'default))
  350.      )
  351.     )
  352.   )
  353.  
  354. (defun eif-set-font (face font)
  355.   "Set the FACE's font to FONT if FONT is a string, to the default font if FONT is 'default, or to the font of the surrounding text if FONT is 'context"
  356.   (cond ((stringp font)
  357.      ;; If the specified font is not useable, use 'default:
  358.      (condition-case error
  359.              (set-face-font face font)
  360.            (error 
  361.         (progn
  362.           (message "eif-set-font failed for face %s and font %s. Setting to 'default" face font)
  363.           (eif-set-font face 'default)))
  364.        )
  365.      )
  366.     ((eq font 'context)
  367.      (set-face-font face nil)
  368.      )
  369.     ((eq font 'default)
  370.      (set-face-font face (face-font 'default))
  371.      )
  372.     )
  373.   )
  374.  
  375. (defun eif-supports-color-p ()
  376.   (and (not disable-color)
  377.        (or (and (fboundp 'display-color-p)
  378.         (display-color-p))
  379.        (and (fboundp 'x-display-color-p)
  380.         (x-display-color-p))
  381.        (and (fboundp 'x-color-display-p)
  382.         (x-color-display-p))
  383.        )
  384.        )
  385.   )
  386.  
  387. (defun eif-init-color ()
  388.   "Reset the Eiffel fonts and faces from the values of their repective variables"
  389.   (make-face 'eif-comment)
  390.   (make-face 'eif-hidden-comment)
  391.   (make-face 'eif-major-keyword)
  392.   (make-face 'eif-minor-keyword)
  393.   (make-face 'eif-quoted-feature)
  394.   (make-face 'eif-assertion)
  395.   (make-face 'eif-string)
  396.  
  397.   (if (eif-supports-color-p)
  398.       (progn
  399.     (eif-set-foreground 'eif-comment         eif-comment-color)
  400.     (eif-set-font       'eif-comment         eif-comment-font)
  401.     (eif-set-foreground 'eif-hidden-comment  eif-hidden-comment-color)
  402.     (eif-set-font       'eif-hidden-comment  eif-hidden-comment-font)
  403.     (eif-set-foreground 'eif-quoted-feature  eif-quoted-feature-color)
  404.     (eif-set-font       'eif-quoted-feature  eif-quoted-feature-font)
  405.     (eif-set-foreground 'eif-major-keyword   eif-major-keyword-color)
  406.     (eif-set-font       'eif-major-keyword   eif-major-keyword-font)
  407.     (eif-set-foreground 'eif-minor-keyword   eif-minor-keyword-color)
  408.     (eif-set-font       'eif-minor-keyword   eif-minor-keyword-font)
  409.     (eif-set-foreground 'eif-assertion       eif-assertion-keyword-color)
  410.     (eif-set-font       'eif-assertion       eif-assertion-keyword-font)
  411.     (eif-set-foreground 'eif-string          eif-string-color)
  412.     (eif-set-font       'eif-string          eif-string-font)
  413.     )
  414.     (eif-set-foreground 'eif-comment         default-foreground-color)
  415.     (eif-set-font       'eif-comment         eif-comment-font)
  416.     (eif-set-foreground 'eif-hidden-comment  default-foreground-color)
  417.     (eif-set-font       'eif-hidden-comment  eif-hidden-comment-font)
  418.     (eif-set-foreground 'eif-quoted-feature  default-foreground-color)
  419.     (eif-set-font       'eif-quoted-feature  eif-quoted-feature-font)
  420.     (eif-set-foreground 'eif-major-keyword   default-foreground-color)
  421.     (eif-set-font       'eif-major-keyword   eif-major-keyword-font)
  422.     (eif-set-foreground 'eif-minor-keyword   default-foreground-color)
  423.     (eif-set-font       'eif-minor-keyword   eif-minor-keyword-font)
  424.     (eif-set-foreground 'eif-assertion       default-foreground-color)
  425.     (eif-set-font       'eif-assertion       eif-assertion-keyword-font)
  426.     (eif-set-foreground 'eif-string          default-foreground-color)
  427.     (eif-set-font       'eif-string          eif-string-font)
  428.     )
  429.  
  430.   (cond ((featurep 'font-lock)
  431.      (copy-face 'eif-comment        'font-lock-comment-face)
  432.      (copy-face 'eif-string         'font-lock-string-face)
  433.      )
  434.     ((and (featurep 'hilit19)
  435.           (not (eq 'eif-comment (car hilit-predefined-face-list)))
  436.           )
  437.      (setq hilit-predefined-face-list
  438.            (append '(eif-comment
  439.              eif-hidden-comment
  440.              eif-major-keyword
  441.              eif-minor-keyword
  442.              eif-quoted-feature
  443.              eif-assertion
  444.              eif-string
  445.             )
  446.                hilit-predefined-face-list
  447.                )
  448.            )
  449.      )
  450.     )
  451.   )
  452.  
  453. (eif-init-color)
  454.  
  455. )) ;; matches "(if () (progn" above that checks for a highlighting package
  456.  
  457. (cond ((featurep 'font-lock)
  458.        (copy-face 'eif-comment        'font-lock-comment-face)
  459.        (copy-face 'eif-string         'font-lock-string-face)
  460.        (defconst eiffel-font-lock-keywords
  461.      (purecopy
  462.       '(;; major keywords
  463.         ("\\(\\(^[ \t]*\\|[ \t]+\\)creation\\|^deferred[ \t]+class\\|^expanded[ \t]+class\\|^class\\|^feature\\|^indexing\\|\\(^[ \t]*\\|[ \t]+\\)inherit\\|^obsolete\\)[ \t\n]" 0 eif-major-keyword nil)
  464.         ;; assertions
  465.         ("\\(^\\|[^_\n]\\<\\)\\(check\\|ensure then\\|ensure\\|invariant\\|require else\\|require\\|variant\\)\\($\\|\\>[^_\n]\\)" 2 eif-assertion nil)
  466.         ;; minor keywords
  467.         ("\\(^\\|[^_\n]\\<\\)\\(alias\\|all\\|and not\\|and then\\|and\\|as\\|debug\\|deferred\\|do\\|else\\|elseif\\|end\\|export\\|external\\|from\\|frozen\\|if not\\|if\\|implies not\\|implies\\|infix\\|inspect\\|is deferred\\|is unique\\|is\\|like\\|local\\|loop\\|not\\|obsolete\\|old\\|once\\|or else\\|or not\\|or\\|prefix\\|redefine\\|rename\\|rescue\\|retry\\|select\\|strip\\|then\\|undefine\\|unique\\|until\\|when\\|xor\\)\\($\\|\\>[^_\n]\\)" 2 eif-minor-keyword nil)
  468.         ;; hidden comments
  469.         ("--|.*" 0 eif-hidden-comment t)
  470.         ;; quoted expr's in comments
  471.         ("`[^`'\n]*'" 0 eif-quoted-feature t)
  472.         )
  473.       )
  474.      "Regular expressions to use with font-lock mode.")
  475.        (defconst ace-font-lock-keywords
  476.      (purecopy
  477.       '(;; major keywords
  478.         ("^system\\|^default\\|^root\\|^cluster\\|^external\\|[ \t\n]end\\($\\|\\>[^_\n]\\)" 0 eif-major-keyword nil)
  479.         ;; hidden comments
  480.         ("--|.*" 0 eif-hidden-comment t)
  481.         ;; quoted expr's in comments
  482.         ("`[^`'\n]*'" 0 eif-quoted-feature t)
  483.         )
  484.       )
  485.      "Ace regular expressions to use with font-lock mode.")
  486.        )
  487.       ((featurep 'lhilit)
  488.  
  489.        ;; ---- Eiffel mode -----    
  490.        ;; NOTE: The order of keywords below is generally alphabetical except 
  491.        ;; when one keyword is the prefix of another (e.g. "and" & "and then")
  492.        ;; In such cases, the prefix keyword MUST be the last one.
  493.        (defvar eiffel-mode-hilit
  494.      '(
  495.        ("--|.*" nil eif-hidden-comment 4);; hidden comments
  496.        ("--[^\n|].*\\|--$" nil eif-comment 3);; comments
  497.        ("`[^`'\n]*'" nil eif-quoted-feature 5);; quoted expr's in comments
  498.        ("^creation\\|^deferred[ \t]*class\\|^expanded[ \t]*class\\|^class\\|^feature\\|^indexing\\|^inherit\\|^obsolete" nil eif-major-keyword 1);; major keywords
  499.        ("\\(^\\|[^_\n]\\<\\)\\(alias\\|all\\|and not\\|and then\\|and\\|as\\|debug\\|deferred\\|do\\|else\\|elseif\\|end\\|export\\|external\\|from\\|frozen\\|if not\\|if\\|implies not\\|implies\\|infix\\|inspect\\|is deferred\\|is unique\\|is\\|like\\|local\\|loop\\|not\\|obsolete\\|old\\|once\\|or else\\|or not\\|or\\|prefix\\|redefine\\|rename\\|rescue\\|retry\\|select\\|strip\\|then\\|undefine\\|unique\\|until\\|when\\|xor\\)\\($\\|\\>[^_\n]\\)" nil eif-minor-keyword 0 2) ;; minor keywords
  500.        ("\\(^\\|[^_\n]\\<\\)\\(check\\|ensure then\\|ensure\\|invariant\\|require else\\|require\\|variant\\)\\($\\|\\>[^_\n]\\)" nil eif-assertion 2 2) ;; assertions
  501.        ("\\(\"\"\\)\\|\\(\"\\([^\"%]\\|%.\\|%\n\\)+\"\\)" nil eif-string 2);; strings
  502.        ))
  503.        (hilit::mode-list-update "Eiffel" eiffel-mode-hilit)
  504.        ;; ---- Ace mode -----    
  505.        (defvar ace-mode-hilit
  506.      '(
  507.        ("--|.*"    nil eif-hidden-comment 2);; hidden comments
  508.        ("--[^\n|].*\\|--$" nil eif-comment 1);; comments
  509.        ("`[^`'\n]*'" nil eif-quoted-feature 3);; quoted expr's in comments
  510.        ("^system\\|^default\\|^root\\|^cluster\\|^external\\|[ \t\n]end\\($\\|\\>[^_\n]\\)" nil eif-major-keyword);; major keywords
  511.  
  512.        ))
  513.        (hilit::mode-list-update "Ace" ace-mode-hilit)
  514.        )
  515.       ;;
  516.       ;; NOTE: The hilit19 colors and fonts are _not_ set via the eif-*
  517.       ;;       faces, fonts, and foreground variables defined above. They
  518.       ;;       use their own face names which describe the colors and fonts
  519.       ;;       to use. See hilit19.el for more info.
  520.       ((featurep 'hilit19)
  521.  
  522.        ;; ---- Eiffel mode -----    
  523.        ;; NOTE: The order of keywords below is generally alphabetical except 
  524.        ;; when one keyword is the prefix of another (e.g. "and" & "and then")
  525.        ;; In such cases, the prefix keyword MUST be the last one.
  526.        (hilit-set-mode-patterns
  527.     'eiffel-mode
  528.       '(
  529.        ("--|.*" nil eif-hidden-comment 4);; hidden comments
  530.        ("--[^\n|].*\\|--$" nil eif-comment 3);; comments
  531.        ("`[^`'\n]*'" nil eif-quoted-feature 5);; quoted expr's in comments
  532.        ("^creation\\|^deferred[ \t]*class\\|^expanded[ \t]*class\\|^class\\|^feature\\|^indexing\\|^inherit\\|^obsolete" nil eif-major-keyword 1);; major keywords
  533.        ("\\(^\\|[^_\n]\\<\\)\\(alias\\|all\\|and not\\|and then\\|and\\|as\\|debug\\|deferred\\|do\\|else\\|elseif\\|end\\|export\\|external\\|from\\|frozen\\|if not\\|if\\|implies not\\|implies\\|infix\\|inspect\\|is deferred\\|is unique\\|is\\|like\\|local\\|loop\\|not\\|obsolete\\|old\\|once\\|or else\\|or not\\|or\\|prefix\\|redefine\\|rename\\|rescue\\|retry\\|select\\|strip\\|then\\|undefine\\|unique\\|until\\|when\\|xor\\)\\($\\|\\>[^_\n]\\)" 2 eif-minor-keyword 0) ;; minor keywords
  534.        ("\\(^\\|[^_\n]\\<\\)\\(check\\|ensure then\\|ensure\\|invariant\\|require else\\|require\\|variant\\)\\($\\|\\>[^_\n]\\)" 2 eif-assertion 2) ;; assertions
  535.        ("\\(\"\"\\)\\|\\(\"\\([^\"%]\\|%.\\|%\n\\)+\"\\)" nil eif-string 2);; strings
  536.        )
  537.      )
  538.        ;; ---- Ace mode -----    
  539.        (hilit-set-mode-patterns
  540.     'ace-mode
  541.      '(
  542.        ("--|.*"    nil eif-hidden-comment 2);; hidden comments
  543.        ("--[^\n|].*\\|--$" nil eif-comment 1);; comments
  544.        ("`[^`'\n]*'" nil eif-quoted-feature 3);; quoted expr's in comments
  545.        ("^system\\|^default\\|^root\\|^cluster\\|^external\\|[ \t\n]end\\($\\|\\>[^_\n]\\)" nil eif-major-keyword);; major keywords
  546.  
  547.        )
  548.      )
  549.        )
  550.       )
  551. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  552. ;;;     No user-customizable definitions below this point.       ;;;
  553. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  554.  
  555. (defmacro eif-class-level-kw-indent-m () 
  556.   "Indentation amount for Class level keywords (in number of spaces)."
  557.   '(+ (* eif-class-level-kw-indent eif-indent-increment) 
  558.      eif-extra-class-level-kw-indent)
  559. )
  560.  
  561. (defmacro eif-class-level-comment-indent-m () 
  562.   "Indentation amount for Class level comments (in number of spaces)."
  563.   '(+ (* eif-class-level-comment-indent eif-indent-increment) 
  564.      eif-extra-class-level-comment-indent)
  565. )
  566.  
  567. (defmacro eif-inherit-level-kw-indent-m () 
  568.   "Indentation amount for Inherit level keywords (in number of spaces)."
  569.   '(+ (* eif-inherit-level-kw-indent eif-indent-increment) 
  570.      eif-extra-inherit-level-kw-indent)
  571. )
  572.  
  573. (defmacro eif-feature-level-indent-m () 
  574.   "Indentation amount for features (in number of spaces)."
  575.   '(+ (* eif-feature-level-indent eif-indent-increment) 
  576.      eif-extra-feature-level-indent)
  577. )
  578.  
  579. (defmacro eif-feature-level-kw-indent-m () 
  580.   "Indentation amount for Feature level keywords (in number of spaces)."
  581.   '(+ (* eif-feature-level-kw-indent eif-indent-increment) 
  582.      eif-extra-feature-level-kw-indent)
  583. )
  584.  
  585. (defmacro eif-body-comment-indent-m () 
  586.   "Indentation amount for comments in routine bodies (in number of spaces)."
  587.   '(+ (* eif-body-comment-indent eif-indent-increment) 
  588.      eif-extra-body-comment-indent)
  589. )
  590.  
  591. (defmacro eif-feature-level-comment-indent-m () 
  592.   "Indentation amount for Feature level comments (in number of spaces)."
  593.   '(+ (* eif-feature-level-comment-indent eif-indent-increment) 
  594.      eif-extra-feature-level-comment-indent)
  595. )
  596.  
  597. (defmacro eif-check-keyword-indent-m ()
  598.   "Indentation amount for Check keyword (in number of spaces)."
  599.   '(+ (* eif-check-keyword-indent eif-indent-increment) 
  600.      eif-extra-check-keyword-indent)
  601. )
  602.  
  603. (defmacro eif-rescue-keyword-indent-m ()
  604.   "Indentation amount for Rescue keyword (in number of spaces)."
  605.   '(+ (* eif-rescue-keyword-indent eif-indent-increment) 
  606.      eif-extra-rescue-keyword-indent)
  607. )
  608.  
  609. (defmacro eif-then-indent-m ()
  610.   "Indentation amount for `then' appearing on a line by itself (in number of spaces)."
  611.   '(+ (* eif-then-indent eif-indent-increment) 
  612.      eif-extra-then-indent)
  613. )
  614.  
  615. (defmacro eif-continuation-indent-m ()
  616.   "Indentation amount for a statement continuation line (in number of spaces)."
  617.   '(+ (* eif-continuation-indent eif-indent-increment) 
  618.      eif-extra-continuation-indent)
  619. )
  620. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  621. ;;;          Keyword Regular Expression Variables.               ;;;
  622. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  623.  
  624. (defvar eif-all-keywords-regexp 
  625.   "\\(indexing\\|class\\|inherit\\|creation\\|feature\\|invariant\\|rename\
  626. \\|redefine\\|undefine\\|select\\|export\\|require\\|local\\|deferred\
  627. \\|do\\|once\\|ensure\\|alias\\|external\\|check\\|rescue\\|debug\\|if\
  628. \\|inspect\\|from\\|else\\|elseif\\|when\\|until\\|variant\\|loop\\|then\
  629. \\|obsolete\\|end\\)[^a-z0-9_]"
  630.   "Regular Expression to identify the presence of any eiffel keyword in a line.
  631. Does not include `is'."
  632.   )
  633.  
  634. ;; Note invariant is handled as a special case since it is both a 
  635. ;; class-level and a from-level keyword
  636. ;; Note obsolete is handled as a special case since it is both a 
  637. ;; class-level and a feature-level keyword
  638. (defvar eif-class-level-keywords 
  639.   "\\(indexing\\|class\\|deferred[ \t]*class\\|expanded[ \t]*class\\|inherit\\|creation\\|feature\\)[^a-z0-9_]" 
  640.   "Those keywords introducing class-level clauses. Note that `invariant'
  641. and `obsolete' are not included here since can function as more than one type of keyword. "
  642.   )
  643.  
  644. (defvar eif-inherit-level-keywords 
  645.   "\\(rename\\|redefine\\|undefine\\|select\\|export\\)" 
  646.   "Those keywords which introduce subclauses of the inherit clause."
  647.   )
  648.  
  649. (defvar eif-feature-level-keywords 
  650.   "\\(require\\|local\\|deferred\\|do\\|once\\|ensure\\|alias\\|external\\)[^a-z0-9_]"
  651.   "Those keywords which are internal to features (in particular, routines)."
  652.   )
  653.  
  654. (defvar eif-end-keyword "end" "The `end' keyword.")
  655.  
  656. (defvar eif-end-on-current-line ".*[ \t]end[ \t]*;?[ \t]*\\(--.*\\)?$" 
  657.   "Regular expression to identify lines ending with the `end' keyword")
  658.  
  659. (defvar eif-non-id-char-regexp "[^a-z0-9_]" 
  660.   "The characters that are not part of identifiers.")
  661.  
  662. (defvar eif-end-keyword-regexp "[^a-z0-9_]end[^a-z0-9_]" 
  663.   "The `end' keyword with context.")
  664.  
  665. (defvar eif-end-matching-keywords
  666.   "\\(check\\|class\\|feature\\|rename\\|redefine\\|undefine\\|select\\|export\\|do\\|once\\|deferred\\|external\\|alias\\|if\\|inspect\\|from\\|debug\\)[^a-z0-9_]"
  667.   "Those keywords whose clause is terminated by an `end' keyword."
  668.   )
  669.  
  670. (defvar eif-control-flow-keywords 
  671.   "\\(if\\|inspect\\|from\\|debug\\)"
  672.   "Keywords which introduce control-flow constructs."
  673.   )
  674.  
  675. (defvar eif-control-flow-matching-keywords
  676.   "\\(deferred\\|do\\|once\\|if\\|inspect\\|from\\|debug\\)[^a-z0-9_]" 
  677.   "Keywords whose occurrence prior to a control-flow-keyword causes the
  678. indentation of the control-flow-keyword. Note that technically,
  679. `end' is part of this list but it is handled separately in the
  680. functions: eif-matching-indent and eif-matching-kw."
  681.   )
  682.  
  683. (defvar eif-check-keyword "check"  "The `check' keyword.")
  684.  
  685. (defvar eif-check-keywords   "\\(check\\)[^a-z0-9_]"  
  686.   "The `check' keyword (with trailing context).")
  687.  
  688. (defvar eif-check-matching-keywords 
  689.   "\\(deferred\\|do\\|once\\|if\\|inspect\\|from\\|debug\\)[^a-z0-9_]"
  690.   "Keywords whose occurrence prior to a check-keyword causes the
  691. indentation of the check-keyword. Note that technically, `end' is
  692. part of this list but it is handled separately in the functions:
  693. eif-matching-indent and eif-matching-kw. (see also
  694. eif-control-flow-matching-keywords)"
  695.   )
  696.  
  697. (defvar eif-rescue-keyword "rescue"  "The `rescue' keyword.")
  698.  
  699. (defvar eif-obsolete-keyword "obsolete"  "The `obsolete' keyword.")
  700.  
  701. (defvar eif-rescue-keywords   "\\(rescue\\)[^a-z0-9_]"  
  702.   "The `rescue' keyword (with trailing context).")
  703.  
  704. (defvar eif-rescue-matching-keywords 
  705.   "\\(deferred\\|do\\|once\\)[^a-z0-9_]"
  706.   "Keywords whose occurrence prior to a rescue-keyword causes the
  707. indentation of the rescue-keyword. Note that technically, `end' is
  708. part of this list but it is handled separately in the functions:
  709. eif-matching-indent and eif-matching-kw. (see also
  710. eif-control-flow-matching-keywords)"
  711.   )
  712.  
  713. (defvar eif-from-level-keywords 
  714.   "\\(until\\|variant\\|loop\\)[^a-z0-9_]"
  715.   "Keywords occuring inside of a from clause."
  716.   )
  717.  
  718. (defvar eif-from-keyword  "from" "The keyword `from'.")
  719.  
  720. (defvar eif-if-or-inspect-level-keywords "\\(elseif\\|else\\|when\\)[^a-z0-9_]"
  721.   "Keywords occuring inside of an if or inspect clause."
  722.   )
  723.  
  724. (defvar eif-if-or-inspect-keyword "\\(if\\|inspect\\)[^a-z0-9_]"
  725.   "The `if' or `inspect' keywords."
  726.   )
  727.  
  728. (defvar eif-then-keyword ".*[ \t)]then[ \t]*$" 
  729.   "The keyword `then' with possible leading text.")
  730.  
  731. (defvar eif-solitary-then-keyword "then" "The keyword `then'.")
  732.  
  733. (defvar eif-then-matching-keywords "\\(if\\|elseif\\|when\\)"
  734.   "Keywords whose occurrence prior to a then-keyword sets the
  735. indentation of the then-keyword. Note that technically, `end' is
  736. part of this list but it is handled separately in the functions:
  737. eif-matching-indent and eif-matching-kw. (see also
  738. eif-control-flow-matching-keywords)"
  739.   )
  740.  
  741. (defvar eif-invariant-keyword "invariant" "The `invariant' keyword.")
  742.  
  743. (defvar eif-invariant-matching-keywords 
  744.   "\\(from\\|feature\\)"
  745.   "Keywords whose occurrence prior to an invariant-keyword causes the
  746. indentation of the invariant-keyword. Note that technically, `end'
  747. is part of this list but it is handled separately in the functions:
  748. eif-matching-indent and eif-matching-kw. (see also
  749. eif-control-flow-matching-keywords)"
  750.   )
  751.  
  752. (defvar eif-obsolete-matching-keywords 
  753.   "\\(is\\|class\\)"
  754.   "Keywords whose occurrence prior to an obsolete-keyword causes the
  755. indentation of the obsolete-keyword."
  756.   )
  757.  
  758. (defvar eif-white-space-regexp       "[     ]*"
  759.   "RE to locate whitespace.")
  760.  
  761. (defvar eif-comment-line-regexp      "[     ]*\\(--.*\\)$" 
  762.   "RE to match a line with a comment on it.")
  763.  
  764. (defvar eif-non-source-line          "[     ]*\\(--.*\\)?$" 
  765.   "RE to match a line with a only a comment or whitespace.")
  766.  
  767. (defvar eif-variable-or-const-regexp "[^()\n]*:[^=].*" 
  768.   "RE to match a variable or constant declaration.")
  769.  
  770. (defvar eif-indentation-keywords-regexp 
  771.   "\\(indexing\\|class\\|check\\|rescue\\|inherit\\|creation\\|feature\\|invariant\\|rename\\|redefine\\|undefine\\|select\\|export\\|require\\|local\\|deferred\\|do\\|once\\|ensure\\|alias\\|external\\|if\\|inspect\\|from\\|debug\\|else\\|elseif\\|when\\|until\\|variant\\|invariant\\|loop\\|obsolete\\)[^a-z0-9_]"
  772.   "RE to identify the presence of any eiffel keyword triggering indentation"
  773.   )
  774.  
  775. (defvar eif-feature-indentation-keywords-regexp 
  776.   "\\(creation\\|feature\\)[^a-z0-9_]"
  777.   "Keywords which denote the presence of features following them."
  778.   )
  779.  
  780. (defvar eif-is-keyword-regexp "\\(.*[     )]\\)?is[     ]*\\(--.*\\)?$"
  781.   "The `is' keyword (with some context)."
  782.   )
  783.  
  784. (defvar eif-multiline-routine-is-keyword-regexp
  785.   ".*([^)]*)\\([ \t\n]*\\|[ \t\n]*:[][ \t\nA-Za-x0-9_,]*\\)is[     ]*\\(--.*\\)?$"
  786.   "The `is' keyword (with some context)."
  787.   )
  788.  
  789. (defvar eif-operator-regexp
  790.   "[     ]*\\([@*/+]\\|-[^-]\\|\\<and[     (]\\|\\<or[     (]\\)"
  791.   "Eiffel operators - used to identify continuation lines"
  792.   )
  793.  
  794. (defvar eif-operator-eol-regexp
  795.   ".*\\([@*/+-]\\|\\<and\\|\\<or\\|:=\\)[     ]*$"
  796.   "Eiffel operators - used to identify continuation lines"
  797.   )
  798.  
  799. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  800.  
  801. (defvar eif-matching-indent -1 
  802.   "The indentation of the keyword found on the last call to eif-matching-kw. 
  803. -1 if no match was found."
  804.   )
  805.  
  806. (defvar eif-matching-kw-for-end nil)
  807.  
  808. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  809. ;;;                      Indentation Functions.                  ;;;
  810. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  811.  
  812. (defun eif-calc-indent ()
  813.   "Calculate the indentation of the current line of eiffel code. This
  814. function generally assumes that the preceding line of code is
  815. indented properly, although lines containing certain class-level
  816. constructs do not require correct indentation of the preceding line."
  817.   (let ((indent   0)
  818.     (line-end 0)
  819.     (originally-looking-at-comment nil)
  820.     (kw-match nil)
  821.     (continuation)
  822.     (id-colon)
  823.     )
  824.     
  825.     (save-excursion
  826.       
  827.       ;; Save location of line-end and skip past leading white space.
  828.       (end-of-line)
  829.       (setq line-end   (point))
  830.       (beginning-of-line)
  831.       (re-search-forward eif-white-space-regexp line-end t)
  832.       
  833.       ;; Is the line we are trying to indent a comment line?
  834.       (setq originally-looking-at-comment (looking-at eif-comment-line-regexp))
  835.       
  836.       ;; Look for a keyword on the current line
  837.       (if (looking-at eif-all-keywords-regexp)
  838.       
  839.       ;; Then we are looking at a keyword
  840.       (cond ((looking-at eif-class-level-keywords)
  841.          ;; File level keywords (indent defaults to 0)
  842.          (setq indent (eif-class-level-kw-indent-m))
  843.          )
  844.         ((looking-at eif-inherit-level-keywords)
  845.          ;; Inherit level keywords (indent defaults to 
  846.          ;; 2*eif-indent-increment)
  847.          (setq indent (eif-inherit-level-kw-indent-m))
  848.          )
  849.         ((looking-at eif-feature-level-keywords)
  850.          ;; Feature level keywords (indent defaults to 
  851.          ;; (eif-feature-level-indent-m) + eif-indent-increment)
  852.          (setq indent (eif-feature-level-kw-indent-m))
  853.          )
  854.         ((looking-at eif-end-keyword)
  855.          ;; End keyword (indent to level of matching keyword)
  856.          (if (string-match "end" 
  857.                    (eif-matching-kw eif-end-matching-keywords))
  858.              ;; Then 
  859.              (if (= eif-matching-indent 
  860.                 (eif-feature-level-kw-indent-m))
  861.              ;; Then
  862.              (setq indent (eif-class-level-kw-indent-m))
  863.                ;; Else
  864.                (setq indent 
  865.                  (- eif-matching-indent eif-indent-increment))
  866.                )
  867.            ;; Else
  868.            (setq indent eif-matching-indent)
  869.            )
  870.          (if (<= indent (eif-feature-level-indent-m))
  871.              (save-excursion
  872.                (end-of-line)
  873.                (while (and (< (point) (point-max))
  874.                    (or (forward-char 1) t)
  875.                    (looking-at eif-non-source-line)
  876.                    )
  877.              (end-of-line)
  878.              )
  879.                (if (not (looking-at eif-non-source-line))
  880.                (setq indent (eif-inherit-level-kw-indent-m))
  881.              (setq indent (eif-class-level-kw-indent-m))
  882.              )
  883.                )
  884.            )
  885.          )
  886.         ((looking-at eif-control-flow-keywords)
  887.          ;; Control flow keywords 
  888.          ;;  Indent to same level as a preceding "end" or
  889.          ;;  if no preceding "end" is found, indent to the level
  890.          ;;  of the preceding "do" plus the value of 
  891.          ;;  eif-indent-increment
  892.          (setq kw-match 
  893.                (eif-matching-kw eif-control-flow-matching-keywords)) 
  894.          (cond ((string-match "end" kw-match)
  895.             (setq indent eif-matching-indent)
  896.             )
  897.                (t
  898.             (setq indent 
  899.                   (+ eif-matching-indent eif-indent-increment)
  900.                   )
  901.             )
  902.                )
  903.          )
  904.         ((looking-at eif-check-keywords)
  905.          ;; Check keyword
  906.          ;;  Indent to level of preceding "end"+eif-indent-increment or
  907.          ;;  if no preceding "end" is found, indent to the level
  908.          ;;  of the preceding eif-check-matching-keywords plus the 
  909.          ;;  value (eif-indent-increment + eif-check-keyword-indent).
  910.          (setq kw-match (eif-matching-kw eif-check-matching-keywords)) 
  911.          (cond ((string-match "end" kw-match)
  912.             (setq indent (+ eif-matching-indent 
  913.                     (eif-check-keyword-indent-m)
  914.                     )
  915.                   )
  916.             )
  917.                (t
  918.             (setq indent 
  919.                   (+ eif-matching-indent 
  920.                  (+ eif-indent-increment 
  921.                     (eif-check-keyword-indent-m)
  922.                     )
  923.                  )
  924.                   )
  925.             )
  926.                )
  927.          )
  928.         ((looking-at eif-rescue-keywords)
  929.          ;; Rescue keyword
  930.          ;;  Indent to level of preceding "end"+eif-indent-increment or
  931.          ;;  if no preceding "end" is found, indent to the level
  932.          ;;  of the preceding eif-rescue-matching-keywords plus the 
  933.          ;;  value (eif-indent-increment + eif-rescue-keyword-indent).
  934.          (setq kw-match (eif-matching-kw eif-rescue-matching-keywords)) 
  935.          (cond ((string-match "end" kw-match)
  936.             (setq indent (+ eif-matching-indent 
  937.                     (eif-rescue-keyword-indent-m)
  938.                     )
  939.                   )
  940.             )
  941.                (t
  942.             (setq indent eif-matching-indent)
  943.             )
  944.                )
  945.          )
  946.         ((looking-at eif-from-level-keywords)
  947.          ;; From level keywords (indent to level of matching "From")
  948.          (if (string-match "end" (eif-matching-kw eif-from-keyword))
  949.              ;; Closest matching KW is `end'.
  950.              (setq indent (- eif-matching-indent eif-indent-increment))
  951.            ;; Closest matching KW is one of `eif-from-keyword'.
  952.            (setq indent eif-matching-indent)
  953.            )
  954.          )
  955.         ((looking-at eif-if-or-inspect-level-keywords)
  956.          ;; If level keywords (indent to level of matching 
  957.          ;; "If" or "Inspect")
  958.          (if (string-match "end" 
  959.                    (eif-matching-kw eif-if-or-inspect-keyword)
  960.                    )
  961.              ;; Closest matching KW is `end'.
  962.              (setq indent (- eif-matching-indent eif-indent-increment))
  963.            ;; Closest matching KW is one of `eif-if-or-inspect-keyword'.
  964.            (setq indent eif-matching-indent)
  965.            )
  966.          )
  967.         ((looking-at eif-solitary-then-keyword)
  968.          ;; Handles case where "then" appears on a line by itself
  969.          ;;   (Indented to the level of the matching if, elseif or when)
  970.          (setq indent (+ (eif-matching-indent eif-then-matching-keywords) 
  971.                  (eif-then-indent-m)
  972.                  )
  973.                )
  974.          )
  975.         ((looking-at eif-invariant-keyword)
  976.          ;; Invariant keyword
  977.          ;;   (Indented to the level of the matching from or feature)
  978.          (if (string-match "from" 
  979.                    (eif-matching-kw eif-invariant-matching-keywords)
  980.                    )
  981.              ;; Then - loop invariant
  982.              (setq indent eif-matching-indent)
  983.            ;; Else - class invariant
  984.            (setq indent (eif-class-level-kw-indent-m))
  985.            )
  986.          )
  987.         ((looking-at eif-obsolete-keyword)
  988.          ;; Obsolete keyword
  989.          ;;   (Indented to the level of the matching from or feature)
  990.          (if (string-match "is" 
  991.                    (eif-matching-kw eif-obsolete-matching-keywords)
  992.                    )
  993.              ;; Then - feature obsolete
  994.              (setq indent (eif-feature-level-kw-indent-m))
  995.            ;; Else - class obsolete
  996.            (setq indent (eif-class-level-kw-indent-m))
  997.            )
  998.          )        ;; end of cond
  999.         )
  1000.     
  1001.     ;; Else no keyword on current line, 
  1002.     ;;   are we in a multi-line parenthesis expression
  1003.     
  1004.     (if (or (and (> (eif-in-paren-expression) 0)
  1005.              (> (setq indent (eif-indent-multi-line)) -1)
  1006.              )
  1007.         (setq indent (eif-manifest-array-indent))
  1008.         )
  1009.         
  1010.         ;; multi-line parenthesis expression
  1011.         ;; Move string continuation lines one column to the left 
  1012.         (if (looking-at "%")
  1013.         (setq indent (1- indent))
  1014.           )
  1015.       
  1016.       ;; Else Find the first preceding line with non-comment source on it
  1017.       ;; that is not a continuation line of a multi-line parnethesized
  1018.       ;; expression.
  1019.  
  1020.       ;; Record whether this line begins with an operator. We assume 
  1021.       ;; that the line is a continuation line if it begins with an operator
  1022.       (beginning-of-line)
  1023.       (if (looking-at eif-operator-regexp)
  1024.           (setq continuation t)
  1025.         (setq continuation nil)
  1026.         )
  1027.       ;; Record whether the line being indented begins with an "<id> :"
  1028.       ;; This is used in indenting assertion tag expressions.
  1029.       (if (looking-at "[     ]*[a-zA-Z0-9_]+[     ]*:")
  1030.           (setq id-colon t)
  1031.         (setq id-colon nil)
  1032.         )
  1033.       
  1034.       (forward-line -1)
  1035.       (beginning-of-line)
  1036.       (while (and (looking-at eif-non-source-line) (not (= (point) 1)))
  1037.         (previous-line 1)
  1038.         (beginning-of-line)
  1039.         )
  1040.       (if (eif-line-contains-close-paren)
  1041.           (backward-sexp)
  1042.         )
  1043.       (end-of-line)
  1044.       (setq line-end (point))
  1045.       (beginning-of-line)
  1046.       (re-search-forward eif-white-space-regexp line-end t)
  1047.       
  1048.       (cond ((and (= (point) 1)
  1049.               originally-looking-at-comment
  1050.               (setq indent (eif-class-level-comment-indent-m))
  1051.               )
  1052.          )
  1053.         ;; 'eif-is-keyword-regexp' case must precede 
  1054.         ;; '(not eif-all-keywords-regexp)' case since "is" is not 
  1055.         ;; part of 'eif-all-keywords-regexp'
  1056.         ((or (looking-at eif-is-keyword-regexp)
  1057.              (looking-at eif-multiline-routine-is-keyword-regexp)
  1058.              (looking-at eif-obsolete-keyword) 
  1059.              )
  1060.          (if originally-looking-at-comment
  1061.              ;; Then  the line we are trying to indent is a comment
  1062.              (setq indent (eif-feature-level-comment-indent-m))
  1063.            ;; Else  the line being indented is not a comment
  1064.            (setq indent (eif-feature-level-kw-indent-m))
  1065.            )
  1066.          )
  1067.         ((looking-at eif-feature-indentation-keywords-regexp)
  1068.          (setq indent (eif-feature-level-indent-m))
  1069.          )
  1070.         ((looking-at eif-indentation-keywords-regexp)
  1071.          (if (looking-at eif-end-on-current-line)
  1072.              (setq indent (eif-current-line-indent))
  1073.            (setq indent 
  1074.              (+ (eif-current-line-indent) eif-indent-increment))
  1075.            )
  1076.          )
  1077.         ((looking-at eif-solitary-then-keyword)
  1078.          (setq indent (- (+ (eif-current-line-indent) eif-indent-increment)
  1079.                  (eif-then-indent-m)
  1080.                  )
  1081.                )
  1082.          )
  1083.         ((looking-at eif-then-keyword)
  1084.          (setq indent (eif-current-line-indent))
  1085.          )
  1086.         ((looking-at (concat eif-end-keyword eif-non-id-char-regexp))
  1087.          (if (= (setq indent (eif-current-line-indent)) 
  1088.             (eif-feature-level-kw-indent-m)
  1089.             )
  1090.              (setq indent (eif-feature-level-indent-m))
  1091.            (eif-matching-line)
  1092.            (if (string-match eif-check-keyword eif-matching-kw-for-end)
  1093.                (setq indent (- indent (eif-check-keyword-indent-m)))
  1094.              )
  1095.            )
  1096.          )
  1097.         ((looking-at eif-variable-or-const-regexp)
  1098.          ;;Either a variable declaration or a pre or post condition tag
  1099.          (if originally-looking-at-comment
  1100.              ;; Then  the line we are trying to indent is a comment
  1101.              (if (= (setq indent (eif-current-line-indent)) 
  1102.                 (eif-feature-level-indent-m)
  1103.                 )
  1104.              ;; Then - a feature level comment
  1105.              (setq indent (eif-feature-level-comment-indent-m))
  1106.                ;; Else - some other kind of comment
  1107.                (setq indent (+ indent (eif-body-comment-indent-m)))
  1108.                )
  1109.            ;; Else  the line being indented is not a comment
  1110.            (if (setq indent (eif-indent-assertion-continuation id-colon))
  1111.                indent
  1112.              (setq indent (eif-current-line-indent))
  1113.              )
  1114.            )
  1115.          )
  1116.         ((setq indent (eif-manifest-array-start))
  1117.          indent
  1118.          )
  1119.         ((not (looking-at eif-all-keywords-regexp))
  1120.          (if originally-looking-at-comment
  1121.              ;; Then  the line we are trying to indent is a comment
  1122.              (cond ((eif-continuation-line)
  1123.                 (setq indent 
  1124.                   (+ (- (eif-current-line-indent) 
  1125.                     eif-indent-increment
  1126.                     )
  1127.                      (eif-body-comment-indent-m)
  1128.                      )
  1129.                   )
  1130.                 )
  1131.                ;; preceding line is at eif-feature-level-indent - 
  1132.                ;; assume that the preceding line is a parent 
  1133.                ;; class in an inherit clause
  1134.                ((= (eif-current-line-indent) 
  1135.                    (eif-feature-level-indent-m)
  1136.                    )
  1137.                 (setq indent 
  1138.                   (+ (eif-inherit-level-kw-indent-m)
  1139.                      (eif-body-comment-indent-m)
  1140.                      )
  1141.                   )
  1142.                 )
  1143.                (t
  1144.                 (setq indent 
  1145.                   (+ (eif-current-line-indent)
  1146.                      (eif-body-comment-indent-m)
  1147.                      )
  1148.                   )
  1149.                 )
  1150.                )
  1151.            ;; Else line being indented is not a comment
  1152.  
  1153.            ;; The line the point is on is the one above the line being
  1154.            ;; indented
  1155.            (beginning-of-line)
  1156.            (if (or continuation (looking-at eif-operator-eol-regexp))
  1157.                ;; Then the line being indented is a continuation line
  1158.                (if  (eif-continuation-line)
  1159.                ;; The line preceding the line being indented is 
  1160.                ;; also a continuation line. Indent to the current
  1161.                ;; line indentation.
  1162.                (setq indent (eif-current-line-indent))
  1163.              ;; Else The line preceding the line being indented is 
  1164.              ;; not a continuation line. Indent an extra 
  1165.              ;; eif-continuation-indent
  1166.              (setq indent (+ (eif-current-line-indent)
  1167.                      (eif-continuation-indent-m)))
  1168.              )
  1169.              ;; Else the line being indented is not a continuation line.
  1170.              (if (eif-continuation-line)
  1171.              (if id-colon
  1172.                  ;; Then the line preceding the one being indented
  1173.                  ;; is an assertion continuation. Indent the current
  1174.                  ;; line to the same level as the preceding assertion
  1175.                  ;; tag.
  1176.                  (setq indent (eif-indent-assertion-tag))
  1177.                ;; Then the line preceding the one being indented is 
  1178.                ;; a continuation line. Un-indent by an 
  1179.                ;; eif-continuation-indent.
  1180.                (setq indent (- (eif-current-line-indent) 
  1181.                        eif-indent-increment
  1182.                        )
  1183.                  )
  1184.                )
  1185.                ;; Else the line preceding the line being indented is
  1186.                ;; also not a continuation line. Use the current indent.
  1187.                (setq indent (eif-current-line-indent))
  1188.                )
  1189.              )
  1190.            )
  1191.          )
  1192.         ) ;; cond
  1193.       ) ;; if
  1194.     ) ;; if
  1195.       ) ;; save-excursion
  1196.     indent
  1197.     ) ;; let
  1198.   )
  1199.  
  1200. (defun eif-continuation-line ()
  1201.   (or (looking-at eif-operator-regexp)
  1202.       (save-excursion 
  1203.     (forward-line -1)
  1204.     (beginning-of-line)
  1205.     (looking-at eif-operator-eol-regexp)
  1206.     )
  1207.       )
  1208.   )
  1209.  
  1210. (defun eif-indent-assertion-continuation (id-colon)
  1211.   "Are we inside a pre or a post condition clause on a line that is a
  1212. continuation of a multi-line assertion beginning with a tag?  If so, return
  1213. the indentation of the continuation line."
  1214.   (let ((limit (point)))
  1215.     (if (save-excursion 
  1216.       (if (re-search-backward (concat eif-feature-level-keywords "\\|"
  1217.                       eif-end-keyword-regexp) nil t) 
  1218.           (if (looking-at "ensure\\|require")
  1219.           (setq limit (point))
  1220.         nil
  1221.         )
  1222.         nil
  1223.         )
  1224.       )
  1225.     (save-excursion
  1226.       (end-of-line)
  1227.       (if (and (not id-colon) (re-search-backward ": *" limit t))
  1228.           (progn
  1229.         (goto-char (match-end 0))
  1230.         (current-column)
  1231.         )
  1232.         nil
  1233.         )
  1234.       )
  1235.       nil
  1236.       )
  1237.     )
  1238.   )
  1239.  
  1240. (defun eif-indent-assertion-tag ()
  1241.   "Are we inside a pre or a post condition clause on a line that is a
  1242. continuation of a multi-line assertion beginning with a tag?  If so, return
  1243. the indentation of the continuation line."
  1244.   (let (indent)
  1245.     (save-excursion 
  1246.       (if (re-search-backward "ensure\\|require\\|variant\\|invariant" nil t)
  1247.       (setq indent (+ (eif-current-line-indent) eif-indent-increment))
  1248.     ;; This option should not occur
  1249.     (error "Could not find assertion tag.")
  1250.     )
  1251.       )
  1252.     )
  1253.   )
  1254.  
  1255. (defun eif-matching-indent (matching-keyword-regexp)
  1256.   "Search backward from the point looking for one of the keywords
  1257. in the MATCHING-KEYWORD-REGEXP. Return the indentation of the
  1258. keyword found. If an `end' keyword occurs prior to finding one of
  1259. the keywords in MATCHING-KEYWORD-REGEXP and it terminates a check
  1260. clause, return the indentation of the `end' minus the value of
  1261. eif-check-keyword-indent."
  1262.   (let ((search-regexp (concat "[^a-z0-9A-Z_]"
  1263.                    eif-end-keyword 
  1264.                    "[^a-z0-9A-Z_]\\|[^a-z0-9A-Z_]" 
  1265.                    matching-keyword-regexp
  1266.                    )
  1267.                )
  1268.     (indent 0)
  1269.     (continue t)
  1270.     )
  1271.     (save-excursion
  1272.       (while (and (re-search-backward search-regexp 1 t)
  1273.           (or (eif-in-quoted-string-p)
  1274.               (eif-in-comment-p)
  1275.               )
  1276.           )
  1277.     )
  1278.       (if (looking-at search-regexp)
  1279.       ;; Then
  1280.       (if (and (looking-at eif-end-keyword-regexp)
  1281.            (eif-matching-line)
  1282.            (string-match eif-check-keyword eif-matching-kw-for-end)
  1283.            )
  1284.           ;; The keyword "end" was found that terminated a "check" clause
  1285.           (setq indent (- (eif-current-line-indent) (eif-check-keyword-indent-m)))
  1286.         ;; Else a keyword in "matching-keyword-regexp" or a normal 
  1287.         ;; "end"was found
  1288.         (setq indent (eif-current-line-indent))
  1289.         )
  1290.     ;; Else
  1291.     (message "No matching indent keyword was found")
  1292.     )
  1293.       indent
  1294.     
  1295.       )
  1296.     )
  1297.   )
  1298.  
  1299. (defun eif-matching-kw (matching-keyword-regexp)
  1300.   "Search backward from the point looking for one of the keywords in
  1301. the MATCHING-KEYWORD-REGEXP. Return the keyword found. Also set the
  1302. value of eif-matching-indent to the indentation of the keyword
  1303. found.  If an `end' keyword occurs prior to finding one of the
  1304. keywords in MATCHING-KEYWORD-REGEXP and it terminates a check
  1305. clause, set the value of eif-matching-indent to the indentation of
  1306. the `end' minus the value of eif-check-keyword-indent."
  1307.   (let ((search-regexp (concat "[^a-z0-9A-Z_.]" 
  1308.                    eif-end-keyword 
  1309.                    "[^a-z0-9A-Z_.]\\|[^a-z0-9A-Z_.]" 
  1310.                    matching-keyword-regexp
  1311.                    )
  1312.                )
  1313.     (keyword "")
  1314.     )
  1315.     (save-excursion
  1316.       ;; Search backward for a matching keyword.
  1317.       (while (and (re-search-backward search-regexp 1 t)
  1318.           (or (eif-in-quoted-string-p)
  1319.               (eif-in-comment-p)
  1320.               )
  1321.           )
  1322.     )
  1323.       (if (looking-at search-regexp)
  1324.       ;; Then - a keyword was found
  1325.       (progn
  1326.         (setq keyword 
  1327.           (buffer-substring (match-beginning 0) (match-end 0))
  1328.           )
  1329.         (if (and (looking-at eif-end-keyword-regexp)
  1330.              (eif-matching-line)
  1331.              (string-match eif-check-keyword eif-matching-kw-for-end)
  1332.              )
  1333.         ;; Then
  1334.         (setq eif-matching-indent 
  1335.               (- (eif-current-line-indent) (eif-check-keyword-indent-m))
  1336.               )
  1337.           ;; Else
  1338.           (setq eif-matching-indent (eif-current-line-indent))
  1339.           )
  1340.         )
  1341.     ;; Else no keyword was found. I think this is an error
  1342.     (setq eif-matching-indent 0)
  1343.     (message "No matching indent keyword was found")
  1344.     )
  1345.       keyword
  1346.       )
  1347.     )
  1348.   )
  1349.  
  1350. (defun eif-line-contains-close-paren ()
  1351.   "This function returns t if the current line contains a close paren and
  1352. nil otherwise. If a close paren is found, the point is placed immediately
  1353. after the last close paren on the line. If no paren is found, the point is
  1354. placed at the beginning of the line."
  1355.   (let ((search-min 0))
  1356.     (beginning-of-line)
  1357.     (setq search-min (point))
  1358.     (end-of-line)
  1359.     (if (search-backward ")" search-min t)
  1360.     ;; Then
  1361.     (progn
  1362.       (forward-char 1)
  1363.       t
  1364.       )
  1365.       ;; Else
  1366.       (beginning-of-line)
  1367.       nil
  1368.       )
  1369.     )
  1370.   )
  1371.  
  1372. ;;;; Not Currently Used
  1373. ;;;(defun eif-quoted-string-on-line-p ()
  1374. ;;;  "t if an Eiffel quoted string begins, ends, or is continued 
  1375. ;;;   on current line."
  1376. ;;;  (save-excursion
  1377. ;;;    (beginning-of-line)
  1378. ;;;    ;; Line must either start with optional whitespace immediately followed
  1379. ;;;    ;; by a '%' or include a '\"'.  It must either end with a '%' character
  1380. ;;;    ;; or must include a second '\"' character.
  1381. ;;;    (looking-at "^\\([ \t]*%\\|[^\"\n]*\"\\)[^\"\n]*\\(%$\\|\"\\)")
  1382. ;;;  )
  1383. ;;;)
  1384.  
  1385. (defvar eif-opening-regexp 
  1386.   "\\<\\(external\\|check\\|deferred\\|do\\|once\\|from\\|if\\|inspect\\)\\>"
  1387.   "Keywords that open eiffel nesting constructs."
  1388.   )
  1389. (defvar eif-closing-regexp "\\<end\\>"
  1390.   "Keywords that close eiffel nesting constructs."
  1391.   )
  1392. (defvar eif-do-regexp "\\<do\\|once\\|external\\>"
  1393.   "Keyword that opens eiffel routine body."
  1394.   )
  1395. (defvar eif-opening-or-closing-regexp 
  1396.   (concat "\\(" eif-opening-regexp "\\|" eif-closing-regexp "\\)") 
  1397.   "Keywords that open or close eiffel nesting constructs."
  1398.   )
  1399.  
  1400. ;;;
  1401. ;;; Code to allow indenting whole eiffel blocks
  1402. ;;;
  1403.  
  1404. (defun eif-matching-line (&optional return-line-break direction)
  1405.   "Return the character position of the keyword matching the eiffel
  1406. keyword on the current line. (e.g. a line containing the keyword
  1407. 'do' is matched by a line containing the keyword 'end' and a line
  1408. containing 'end' may be matched by a number of opening keywords.
  1409. If the optional parameter 'return-line-break' is not nil, the
  1410. character position returned is the beginning (or end) of the line
  1411. containing the matching keyword instead of the position of the
  1412. keyword itself. If the second optional parameter, direction, is 
  1413. non-null, the current line is not searched for a keyword. Instead, 
  1414. if the value of direction is 'forward, the function acts as if
  1415. an eif-opening-regexp is on the current line. If the value of direction
  1416. is 'backward, the function acts as if a eif-closing-regexp is on the 
  1417. current line. The effect of using the direction parameter is to 
  1418. locate either the opening or closing keyword of the syntactic 
  1419. construct containing the point."
  1420.   (let ((nesting-level 0)
  1421.     (matching-point nil)
  1422.     (search-end 0)
  1423.     (opening-keyword nil)
  1424.     (match-start nil)
  1425.     (match-end nil)
  1426.     (success   nil)
  1427.     (start-point nil)
  1428.     )
  1429.     (unwind-protect
  1430.     (save-excursion
  1431.       (modify-syntax-entry ?_  "w  ")
  1432.       (setq eif-matching-kw-for-end "");; public variable set by this function
  1433.       (setq start-point (point))
  1434.       (end-of-line)
  1435.       (setq search-end (point))
  1436.       (beginning-of-line)
  1437.       ;; Set starting state: If direction was specified use it.
  1438.       ;; If direction is nil, search for a keyword on the current line
  1439.       ;; If the keyword is in eif-opening-regexp, set the search 
  1440.       ;; direction to 'forward, if the keyword on the current line is `end' 
  1441.       ;; set the search direction to 'backward.
  1442.       (cond ((eq direction 'forward)
  1443.          (end-of-line);; So we wont see any keywords on the current line
  1444.          (setq nesting-level 1)
  1445.          )
  1446.         ((eq direction 'backward)
  1447.          (beginning-of-line);; So we wont see any keywords on the current line
  1448.          (setq nesting-level -1)
  1449.          )
  1450.         ((and (re-search-forward eif-opening-regexp search-end t)
  1451.               (not (or (eif-in-quoted-string-p)
  1452.                    (eif-in-comment-p)
  1453.                    )
  1454.                )
  1455.               )
  1456.          (setq match-start (match-beginning 0))
  1457.          (goto-char match-start) 
  1458.          (if (not (or (eif-in-quoted-string-p) (eif-in-comment-p)))
  1459.              (setq nesting-level 1)
  1460.            )
  1461.          (setq opening-keyword 
  1462.                (cons (buffer-substring match-start (match-end 0))
  1463.                  opening-keyword
  1464.                  )
  1465.                )
  1466.          (goto-char (match-end 0))
  1467.          )
  1468.         ((and (progn (beginning-of-line) t)
  1469.               (re-search-forward eif-closing-regexp search-end t)
  1470.               (not (or (eif-in-quoted-string-p)
  1471.                    (eif-in-comment-p)
  1472.                    )
  1473.                )
  1474.               )
  1475.          (goto-char (match-beginning 0))
  1476.          (if (not (or (eif-in-quoted-string-p) (eif-in-comment-p)))
  1477.              (setq nesting-level -1)
  1478.            )
  1479.          )
  1480.         )
  1481.       ;; Perform the search
  1482.       (while (not (= nesting-level 0))
  1483.         (if (> nesting-level 0)
  1484.         ;; Then search forward for the next keyword not in a comment
  1485.         (while (and (re-search-forward eif-opening-or-closing-regexp nil 1)
  1486.                 (goto-char (setq match-start (match-beginning 0)))
  1487.                 (setq match-end   (match-end 0))
  1488.                 (setq success t)
  1489.                 (or (eif-in-quoted-string-p) (eif-in-comment-p))
  1490.                 )
  1491.           (goto-char match-end)
  1492.           (setq success nil)
  1493.           )
  1494.           ;; Else search backward for the next keyword not in a comment
  1495.           (while (and (re-search-backward eif-opening-or-closing-regexp nil 1)
  1496.               (goto-char (setq match-start (match-beginning 0)))
  1497.               (setq success t)
  1498.               (or (eif-in-quoted-string-p) (eif-in-comment-p))
  1499.               )
  1500.         (setq success nil)
  1501.         )
  1502.           )
  1503.         (cond ((and (looking-at eif-opening-regexp) success)
  1504.            ;; Found an opening keyword
  1505.            (if (> nesting-level 0)
  1506.                ;; Then
  1507.                (if (looking-at eif-do-regexp)
  1508.                ;; Then
  1509.                (setq nesting-level -1)
  1510.              ;; Else
  1511.              (setq opening-keyword 
  1512.                    (cons (buffer-substring match-start (match-end 0))
  1513.                      opening-keyword
  1514.                      )
  1515.                    )
  1516.              (goto-char (match-end 0))
  1517.              )
  1518.              ;; Else
  1519.              (if (= nesting-level -1)
  1520.              ;; Then
  1521.              (progn
  1522.                (setq eif-matching-kw-for-end
  1523.                  (buffer-substring match-start (match-end 0))
  1524.                  )
  1525.                (if (looking-at "[ \t\n]+") (goto-char (match-end 0)))
  1526.                )
  1527.                ;; Else
  1528.                (if (looking-at eif-do-regexp)
  1529.                ;; Then
  1530.                (progn
  1531.                  (goto-char (eif-matching-line nil 'forward))
  1532.                  (setq nesting-level -1)
  1533.                  )
  1534.              )
  1535.                )
  1536.              (setq opening-keyword (cdr opening-keyword))
  1537.              (if return-line-break
  1538.              (beginning-of-line)
  1539.                )
  1540.              )
  1541.            (setq nesting-level (1+ nesting-level))
  1542.            )
  1543.           ((and (looking-at eif-closing-regexp) success)
  1544.            ;; Found an opening keyword
  1545.            (if (> nesting-level 0)
  1546.                ;; Then
  1547.                (progn
  1548.              (setq opening-keyword (cdr opening-keyword))
  1549.              (if return-line-break
  1550.                  (end-of-line)
  1551.                )
  1552.              (goto-char (match-end 0))
  1553.              )
  1554.              ;; Else
  1555.              (setq opening-keyword 
  1556.                (cons (buffer-substring (match-beginning 0) 
  1557.                            (match-end 0)
  1558.                            )
  1559.                  opening-keyword
  1560.                  )
  1561.                )
  1562.              )
  1563.            (setq nesting-level (1- nesting-level))
  1564.            )
  1565.           (t (message (concat "Could not find match"
  1566.                       (if (car opening-keyword) 
  1567.                       (concat " for: " (car opening-keyword))
  1568.                     )
  1569.                       )
  1570.                   )
  1571.              (goto-char start-point)
  1572.              (setq nesting-level 0)
  1573.              )
  1574.           );; cond
  1575.         );; while
  1576.       (setq matching-point (point))      
  1577.       );; save-excursion
  1578.       (modify-syntax-entry ?_  "_  ")
  1579.       );; unwind-protect
  1580.     (set-mark matching-point)
  1581.     );; let
  1582.   );; eif-matching-line 
  1583.  
  1584. ;;; ENHANCEME: Make this function correctly indent more than just routine 
  1585. ;;;            bodies and their sub-constructs. At the least it should 
  1586. ;;;            handle whole routines also.
  1587. (defun eif-indent-construct ()
  1588.   "Indents an entire eiffel syntactic construct. It is assumed that
  1589. the point is within a nesting construct ('do', `once', 'check', 'if',
  1590. 'from', or 'inspect'). The whole construct is indented up to the
  1591. matching end. If the point is not within such a construct, then
  1592. only that line is indented"
  1593.   (interactive)
  1594.   (let ((end-point 0))
  1595.     (save-excursion
  1596.       (end-of-line)
  1597.       (if (not (= (point) (point-max))) (forward-char 1))
  1598.       (goto-char (eif-matching-line t 'backward))
  1599.       (setq end-point (eif-matching-line t 'forward))
  1600.       (while (< (point) end-point)
  1601.     (eif-indent-line)
  1602.     (next-line 1)
  1603.     (beginning-of-line)
  1604.     )
  1605.       )
  1606.     )
  1607.   )
  1608.  
  1609. (defun eif-indent-region (&optional start end)
  1610.   "Indents the lines in the current region"
  1611.   (interactive)
  1612.   (let ((start-point (or start (region-beginning))) 
  1613.     (end-point   (copy-marker (or end (region-end))))
  1614.     )
  1615.     (save-excursion
  1616.       (goto-char start-point)
  1617.       (cond ((eq major-mode 'ace-mode)
  1618.          (while (< (point) end-point)
  1619.            (if (not (looking-at "[     ]*$"))
  1620.            (ace-indent-line)
  1621.          )
  1622.            (next-line 1)
  1623.            (beginning-of-line)
  1624.            )
  1625.          )
  1626.         ((eq major-mode 'eiffel-mode)
  1627.          (while (< (point) end-point)
  1628.            (if (not (looking-at "[     ]*$"))
  1629.            (eif-indent-line)
  1630.          )
  1631.            (next-line 1)
  1632.            (beginning-of-line)
  1633.            )
  1634.          )
  1635.         (t (error "Buffer must be in eiffel or ace mode."))
  1636.         )
  1637.       )
  1638.     )
  1639.   )
  1640.  
  1641. ;;(defun eif-goto-matching-line (&optional direction)
  1642. ;;  "Place the cursor on the line which closes(opens) the current
  1643. ;;opening(closing) syntactic construct. For example if the point
  1644. ;;is on `from', executing goto-matching-line places the point
  1645. ;;on the matching `end' and vice-versa."
  1646. ;;  (interactive)
  1647. ;;  (if (not direction)
  1648. ;;      (progn
  1649. ;;    (cond ((save-excursion (beginning-of-line) (looking-at "[     ]*end.*$"))
  1650. ;;           (goto-char (eif-matching-line nil 'backward))
  1651. ;;           )
  1652. ;;          ((looking-at "(")
  1653. ;;           (forward-sexp)
  1654. ;;           )
  1655. ;;          ((save-excursion (backward-char 1) (looking-at ")"))
  1656. ;;           (backward-sexp)
  1657. ;;           )
  1658. ;;          (t
  1659. ;;           (goto-char (eif-matching-line nil 'forward))
  1660. ;;           )
  1661. ;;          )
  1662. ;;    )
  1663. ;;    )
  1664. ;;  )
  1665.  
  1666. (defun eif-forward-sexp ()
  1667.   "Place the cursor on the line which closes the current opening syntactic construct. For example if the point is  on `from', executing eif-forward-sexp places the point on the matching `end'. This also does matching of parens ala forward-sexp."
  1668.   (interactive)
  1669.   (cond ((looking-at "[[(]")
  1670.      (forward-sexp)
  1671.      )
  1672.     (t
  1673.      (goto-char (eif-matching-line nil 'forward))
  1674.      )
  1675.     )
  1676.   )
  1677.  
  1678. (defun eif-backward-sexp ()
  1679.   "Place the cursor on the line which opens  the current closing syntactic construct. For example if the point is  on the terminating `end' of an `if' statement, executing  eif-backward-sexp places the point on the opening `if'.  This also does matching of parens ala backward-sexp."
  1680.   (interactive)
  1681.   (cond ((save-excursion (backward-char 1) (looking-at "[])]"))
  1682.      (backward-sexp)
  1683.      )
  1684.     (t
  1685.      (goto-char (eif-matching-line nil 'backward))
  1686.      )
  1687.     )
  1688.   )
  1689.  
  1690. (defun eif-local-indent (amount)
  1691.   "Set the value of eif-indent-increment to amount and make the change local to this buffer."
  1692.   (interactive "NNumber of spaces for eif-indent-increment: ")
  1693.   (make-local-variable 'eif-indent-increment)
  1694.   (setq eif-indent-increment amount)
  1695.   )
  1696.  
  1697. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1698. ;;;                      Utility Functions.                      ;;;
  1699. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1700.  
  1701. (defun eif-feature-quote ()
  1702.   "Put a `' around the current feature name"
  1703.   (interactive)
  1704.   (save-excursion
  1705.     (backward-sexp)
  1706.     (insert "`")
  1707.     (forward-sexp)
  1708.     (insert "'")
  1709.     )
  1710.   (if (looking-at "'")
  1711.       (forward-char 1))
  1712.   )
  1713.  
  1714. (defvar eiffel-mode-abbrev-table nil)
  1715. (define-abbrev-table 'eiffel-mode-abbrev-table ())
  1716.  
  1717. ;;; ----------------------------------------------------------------------
  1718. ;;; This next portion of the file is derived from "eiffel.el"
  1719. ;;; Copyright (C) 1989, 1990 Free Software Foundation, Inc. and Bob Weiner
  1720. ;;; Available for use and distribution under the same terms as GNU Emacs.
  1721. ;;; ----------------------------------------------------------------------
  1722.  
  1723. (defvar eiffel-mode-map nil 
  1724.   "Keymap for Eiffel mode.")
  1725.  
  1726. (defvar eiffel-mode-syntax-table nil
  1727.   "Syntax table in use in Eiffel-mode buffers.")
  1728.  
  1729. (if eiffel-mode-syntax-table
  1730.     nil
  1731.   (let ((table (make-syntax-table))
  1732.     (i 0))
  1733.     (while (< i ?0)
  1734.       (modify-syntax-entry i "_   " table)
  1735.       (setq i (1+ i)))
  1736.     (setq i (1+ ?9))
  1737.     (while (< i ?A)
  1738.       (modify-syntax-entry i "_   " table)
  1739.       (setq i (1+ i)))
  1740.     (setq i (1+ ?Z))
  1741.     (while (< i ?a)
  1742.       (modify-syntax-entry i "_   " table)
  1743.       (setq i (1+ i)))
  1744.     (setq i (1+ ?z))
  1745.     (while (< i 128)
  1746.       (modify-syntax-entry i "_   " table)
  1747.       (setq i (1+ i)))
  1748.     (modify-syntax-entry ?  "    " table)
  1749.     (modify-syntax-entry ?-  ". 12" table)
  1750.     (modify-syntax-entry ?_  "_  " table)
  1751.     (modify-syntax-entry ?\t "    " table)
  1752.     (modify-syntax-entry ?\n ">   " table)
  1753.     (modify-syntax-entry ?\f ">   " table)
  1754.     (modify-syntax-entry ?\" "\"    " table)
  1755.     (modify-syntax-entry ?\\ "." table)
  1756.     (modify-syntax-entry ?\( "()  " table)
  1757.     (modify-syntax-entry ?\) ")(  " table)
  1758.     (modify-syntax-entry ?\[ "(]  " table)
  1759.     (modify-syntax-entry ?\] ")[  " table)
  1760.     (modify-syntax-entry ?\{ "(}  " table)
  1761.     (modify-syntax-entry ?\} "){  " table)
  1762.     (modify-syntax-entry ?' "\"" table)
  1763.     (modify-syntax-entry ?` "." table)
  1764.     (modify-syntax-entry ?/ "." table)
  1765.     (modify-syntax-entry ?* "." table)
  1766.     (modify-syntax-entry ?+ "." table)
  1767.     (modify-syntax-entry ?= "." table)
  1768.     (modify-syntax-entry ?% "\\" table)
  1769.     (modify-syntax-entry ?< "." table)
  1770.     (modify-syntax-entry ?> "." table)
  1771.     (modify-syntax-entry ?& "." table)
  1772.     (modify-syntax-entry ?| "." table)
  1773.     (modify-syntax-entry ?\; "." table)
  1774.     (modify-syntax-entry ?: "." table)
  1775.     (modify-syntax-entry ?! "." table)
  1776.     (modify-syntax-entry ?. "." table)
  1777.     (setq eiffel-mode-syntax-table table))
  1778.     )
  1779.  
  1780. (if eiffel-mode-map
  1781.     nil  
  1782.   (setq eiffel-mode-map (make-sparse-keymap))
  1783.   (define-key eiffel-mode-map "\t" 'eif-indent-line)
  1784.   (define-key eiffel-mode-map "\C-j" 'eif-newline)
  1785.   (if (and (boundp 'eif-cr-function) eif-cr-function)
  1786.       (define-key eiffel-mode-map "\C-m" eif-cr-function)
  1787.     )
  1788.   (define-key eiffel-mode-map "\M-\C-q" 'eif-indent-construct)
  1789.   (define-key eiffel-mode-map "\M-'" 'eif-feature-quote)
  1790.   (define-key eiffel-mode-map "\M-q" 'eif-fill-paragraph)
  1791.   )
  1792.  
  1793. ;;;###autoload
  1794. (defun eiffel-mode ()
  1795.   "Major mode for editing Eiffel programs."
  1796.   (interactive)
  1797.   (setq major-mode 'eiffel-mode)
  1798.   (setq mode-name "Eiffel")
  1799.   (use-local-map eiffel-mode-map)
  1800.   (set-syntax-table eiffel-mode-syntax-table)
  1801.  
  1802.   ;; Make local variables.
  1803.   (make-local-variable 'paragraph-start)
  1804.   (make-local-variable 'paragraph-separate)
  1805.   (make-local-variable 'paragraph-ignore-fill-prefix)
  1806.   (make-local-variable 'require-final-newline)
  1807.   (make-local-variable 'parse-sexp-ignore-comments)
  1808.   (make-local-variable 'indent-line-function)
  1809.   (make-local-variable 'indent-region-function)
  1810.   (make-local-variable 'comment-start)
  1811.   (make-local-variable 'comment-end)
  1812.   (make-local-variable 'comment-column)
  1813.   (make-local-variable 'comment-start-skip)
  1814.   ;; Now set their values.
  1815.   (setq paragraph-start (concat "^$\\|" page-delimiter)
  1816.     paragraph-separate paragraph-start
  1817.     paragraph-ignore-fill-prefix t
  1818.     require-final-newline 'ask
  1819.     parse-sexp-ignore-comments t
  1820.     indent-line-function 'eif-indent-line
  1821.     indent-region-function 'eif-indent-region
  1822.     comment-start "-- "
  1823.     comment-end ""
  1824.     comment-column 32
  1825.     comment-start-skip "--+ *")
  1826.  
  1827.   (run-hooks 'eiffel-mode-hook)
  1828.   (setq local-abbrev-table eiffel-mode-abbrev-table)
  1829.   (setq auto-fill-function 'eif-auto-fill)
  1830.   )
  1831.  
  1832. (defun eif-in-comment-p ()
  1833.   "t if point is in a comment."
  1834.   (save-excursion
  1835.     (and (/= (point) (point-max)) (forward-char 1))
  1836.     (search-backward "--" (save-excursion (beginning-of-line) (point)) t)))
  1837.  
  1838.  
  1839. ;; ENHANCEME: Currently eif-beginning-of-feature only works for routines. 
  1840. ;;            It should be made more general.
  1841. ;;
  1842.  
  1843. (defun eif-beginning-of-feature (&optional arg)
  1844.   "Move backward to next feature beginning. With argument, do this that many 
  1845. times. Returns t unless search stops due to beginning of buffer."
  1846.   (interactive "p")
  1847.   (and arg (< arg 0) (forward-char 1))
  1848.   (if (or (re-search-backward eif-multiline-routine-is-keyword-regexp 
  1849.                   nil t (or arg 1))
  1850.       (re-search-backward eif-is-keyword-regexp 
  1851.                   nil 'move (or arg 1))      
  1852.       )
  1853.       (progn
  1854.     (backward-sexp 1)
  1855.     (if (looking-at "(")
  1856.         (backward-word 1)
  1857.       )
  1858.     (beginning-of-line)
  1859.     )
  1860.     nil
  1861.     )
  1862.   )
  1863.  
  1864. (defun eif-current-line-indent ()
  1865.   "Return the indentation of the line containing the point."
  1866.   (save-excursion
  1867.     (let ((line-end 0)
  1868.       (indent   0)
  1869.       )
  1870.       (end-of-line)
  1871.       (setq line-end (point))
  1872.       (beginning-of-line)
  1873.       (re-search-forward eif-white-space-regexp line-end t)
  1874.       (setq indent (current-column))
  1875.       )
  1876.     )
  1877.   )
  1878.  
  1879. (defun eif-in-quoted-string-p (&optional non-strict-p)
  1880.   "t if point is in a quoted string. Optional argument NON-STRICT-P if true
  1881. causes the function to return true even if the point is located in leading
  1882. white space on a continuation line. Normally leading white space is not
  1883. considered part of the string."
  1884.   (let ((initial-regexp "^[ \t]*%\\|[^%]\"\\|%[ \t]*$")
  1885.     (search-limit (point))
  1886.     (count 0)
  1887.     )
  1888.     (save-excursion
  1889.       ;; Line must either start with optional whitespace immediately followed
  1890.       ;; by a '%' or include a '\"' before the search-limit.
  1891.       (beginning-of-line)
  1892.       (while (re-search-forward initial-regexp search-limit t)
  1893.     (setq count (1+ count))
  1894.     (if (= count 1) (setq search-limit (1+ search-limit)))
  1895.     )
  1896.       ;; If the number of quotes (including continuation line markers) is odd, 
  1897.       ;; then we are inside of a string. Also if non-strict-p and we are in 
  1898.       ;; the leading white space of a continuation line, then we are in a quote.
  1899.       (if (= (% count 2) 1)
  1900.       t
  1901.     (beginning-of-line)
  1902.     (if non-strict-p
  1903.         (if (looking-at "^[ \t]*%")
  1904.         t
  1905.           nil
  1906.           )
  1907.       nil
  1908.       );; if
  1909.     );; if
  1910.       );; save-excursion
  1911.     );; let
  1912.   );; e-in-quoted-string
  1913.  
  1914. ;;; ----------------------------------------------------------------------
  1915. ;;; End of portion derived from "eiffel.el"
  1916. ;;; ----------------------------------------------------------------------
  1917.  
  1918. (defun eif-comment-prefix ()
  1919.   "Prefix that starts a comment that begins a line.
  1920.    Comments that are not the only thing on a line return nil as their prefix."
  1921.   (save-excursion
  1922.     (end-of-line)
  1923.     (let ((limit (point)) len
  1924.       (in-string (eif-in-quoted-string-p))
  1925.       )
  1926.       (beginning-of-line)
  1927.       (cond ((re-search-forward "^[ \t]*--|?[ \t]*" limit t)
  1928.          (buffer-substring (match-beginning 0) (match-end 0))
  1929.          )
  1930.         ;; Handle string-literal continuation lines
  1931.         (in-string
  1932.          (end-of-line)
  1933.          (re-search-backward "^[ \t]*%\\|[^%]\"" nil t)
  1934.          (re-search-forward "%\\|\"" nil t)
  1935.          (setq len (1- (current-column)))
  1936.          (concat (make-string len ? ) "%")
  1937.          )
  1938.         (t    nil)
  1939.         )
  1940.       )
  1941.     )
  1942.   )
  1943.  
  1944.  
  1945. (defun eif-auto-fill ()
  1946.   (let ((fill-prefix (eif-comment-prefix)) (pm (point-marker)))
  1947.     (if (and (> (current-column) fill-column) fill-prefix)
  1948.     (if (string-match "^[ \t]*%" fill-prefix)
  1949.         (progn
  1950.           (backward-char 1)
  1951.           (re-search-backward "[^][a-zA-Z0-9]" nil t)
  1952.           (forward-char 1)
  1953.           (insert "%\n")
  1954.           (insert fill-prefix)
  1955.           (goto-char pm)
  1956.           )
  1957.       ;; (do-auto-fill)
  1958.       (backward-char 1)
  1959.       (re-search-backward "\\s-" nil t)
  1960.       (forward-char 1)
  1961.       (insert "\n")
  1962.       (insert fill-prefix)
  1963.       (goto-char pm)
  1964.       )
  1965.       )
  1966.     )
  1967.   )
  1968.  
  1969. (defun eif-fill-paragraph ()
  1970.   "Textually fills Eiffel comments ala fill-paragraph"
  1971.   (interactive)
  1972.   (save-excursion
  1973.     (let ((current-point (point))
  1974.       (last-point nil)
  1975.       (para-begin nil)
  1976.       (para-end   nil)
  1977.       (fill-prefix (eif-comment-prefix))
  1978.       )
  1979.       (if fill-prefix
  1980.       (progn
  1981.         (setq last-point (point))
  1982.         (forward-line -1)
  1983.         (end-of-line)
  1984.         (while (and (not (= (point) last-point))
  1985.             (eif-comment-prefix)
  1986.             )
  1987.           (setq last-point (point))
  1988.           (forward-line -1)
  1989.           (end-of-line)
  1990.           )
  1991.         (if (= (point) last-point)
  1992.         (setq para-begin (save-excursion (beginning-of-line) (point)))
  1993.           (setq para-begin (1+ (point)))
  1994.           )
  1995.         (goto-char current-point)
  1996.         (setq last-point (point))
  1997.         (next-line 1)
  1998.         (end-of-line)
  1999.         (while (and (not (= (point) last-point))
  2000.             (eif-comment-prefix)
  2001.             )
  2002.           (setq last-point (point))
  2003.           (next-line 1)
  2004.           (end-of-line)
  2005.           )
  2006.         (if (= (point) last-point)
  2007.         (setq para-end (point))
  2008.           (beginning-of-line)
  2009.           (setq para-end (point))
  2010.           )
  2011.         (fill-region para-begin para-end)
  2012.         )
  2013.     )
  2014.       )
  2015.     )
  2016.   )
  2017.   
  2018. (defun eif-newline ()
  2019.   "Insert a newline and indent the new line."
  2020.   (interactive)
  2021.   (insert "\n")
  2022.   (eif-indent-line)
  2023.   )
  2024.  
  2025. (defun eif-indent-and-newline ()
  2026.   "Indent the current line. Insert a newline and indent the new line."
  2027.   (interactive)
  2028.   (eif-indent-line)
  2029.   (insert "\n")
  2030.   (eif-indent-line)
  2031.   )
  2032.  
  2033. (defun eif-indent-line (&optional whole-exp)
  2034.   "Indent the current line as Eiffel code.
  2035. With argument, indent any additional lines of the same clause
  2036. rigidly along with this one (not implemented yet)."
  2037.   (interactive "p")
  2038.   (save-excursion
  2039.     (beginning-of-line)
  2040.     (skip-chars-forward " \t")
  2041.     (let ((indent (eif-calc-indent)))
  2042.       (if (not (= indent (current-column)))
  2043.       (progn
  2044.         (delete-horizontal-space)
  2045.         (indent-to indent)
  2046.         )
  2047.     )
  2048.       )
  2049.     )
  2050.   (skip-chars-forward " \t"))
  2051.  
  2052. (defun eif-move-to-prev-non-blank ()
  2053.   "Moves point to previous line excluding blank lines. 
  2054. Returns t if successful, nil if not."
  2055.   (beginning-of-line)
  2056.   (re-search-backward "^[ \t]*[^ \t\n]" nil t))
  2057.  
  2058. (defvar eif-last-feature-level-indent -1)
  2059. (defvar eif-feature-level-indent-regexp nil)
  2060. (defun eif-in-paren-expression ()
  2061.   "Determine if we are inside of a parenthesized expression"
  2062.   (interactive)
  2063.   (let ((paren-count 0) (limit 0))
  2064.     (save-excursion
  2065.       (if (= eif-last-feature-level-indent (eif-feature-level-indent-m))
  2066.       (setq limit 
  2067.         (re-search-backward eif-feature-level-indent-regexp nil t))
  2068.     (setq eif-last-feature-level-indent (eif-feature-level-indent-m))
  2069.     (setq eif-feature-level-indent-regexp
  2070.           (concat "^" (make-string eif-last-feature-level-indent ? ) 
  2071.               "[^ \t\n]")
  2072.           )
  2073.     (setq limit 
  2074.           (or (re-search-backward eif-feature-level-indent-regexp nil t)
  2075.           0)
  2076.           )
  2077.     )
  2078.       )
  2079.     (save-excursion
  2080.       (while (re-search-backward "[][()]" limit t)
  2081.     (if (looking-at "[[(]")
  2082.         (setq paren-count (1+ paren-count))
  2083.       (setq paren-count (1- paren-count))
  2084.       )
  2085.     )
  2086.       )
  2087.     paren-count
  2088.     )
  2089. )
  2090.  
  2091. (defun eif-manifest-array-indent ()
  2092.   "Determine if we are inside of a manifest array"
  2093.   (interactive)
  2094.   (let ((paren-count 0) (indent nil)
  2095.     (limit 0))
  2096.     (save-excursion
  2097.       (if (= eif-last-feature-level-indent (eif-feature-level-indent-m))
  2098.       (setq limit 
  2099.         (re-search-backward eif-feature-level-indent-regexp nil t))
  2100.     (setq eif-last-feature-level-indent (eif-feature-level-indent-m))
  2101.     (setq eif-feature-level-indent-regexp
  2102.           (concat "^" (make-string eif-last-feature-level-indent ? ) 
  2103.               "[^ \t\n]")
  2104.           )
  2105.     (setq limit 
  2106.           (or (re-search-backward eif-feature-level-indent-regexp nil t)
  2107.           0)
  2108.           )
  2109.     )
  2110.       )
  2111.     (save-excursion
  2112.       (while (and (<= paren-count 0) (re-search-backward "<<\\|>>" nil t))
  2113.     (if (looking-at "<<")
  2114.         (setq paren-count (1+ paren-count))
  2115.       (setq paren-count (1- paren-count))
  2116.       )
  2117.     )
  2118.       (if (> paren-count 0) 
  2119.       (let ((eol (save-excursion (end-of-line) (point))))
  2120.         (setq indent 
  2121.           (or (and (re-search-forward "[^< \t]" eol t)
  2122.                (1- (current-column)))
  2123.               (+ (current-column) 2)
  2124.               )
  2125.           )
  2126.         )
  2127.     )
  2128.       )
  2129.     indent
  2130.     )
  2131.   )
  2132.  
  2133. (defun eif-manifest-array-start ()
  2134.   "Determine the indentation of the statement containing a manifest array"
  2135.   (interactive)
  2136.   (let ((paren-count 0) (indent nil)
  2137.     (limit 0))
  2138.     (save-excursion
  2139.       (if (= eif-last-feature-level-indent (eif-feature-level-indent-m))
  2140.       (setq limit 
  2141.         (re-search-backward eif-feature-level-indent-regexp nil t))
  2142.     (setq eif-last-feature-level-indent (eif-feature-level-indent-m))
  2143.     (setq eif-feature-level-indent-regexp
  2144.           (concat "^" (make-string eif-last-feature-level-indent ? ) 
  2145.               "[^ \t\n]")
  2146.           )
  2147.     (setq limit 
  2148.           (or (re-search-backward eif-feature-level-indent-regexp nil t)
  2149.           0)
  2150.           )
  2151.     )
  2152.       )
  2153.     (save-excursion
  2154.       (while (and (<= paren-count 0) (re-search-backward "<<\\|>>" nil t))
  2155.     (if (looking-at "<<")
  2156.         (setq paren-count (1+ paren-count))
  2157.       (setq paren-count (1- paren-count))
  2158.       )
  2159.     )
  2160.       (if (> paren-count 0) 
  2161.       (let ((limit (progn (end-of-line) (point))))
  2162.         (beginning-of-line)
  2163.         (if (re-search-forward "^[ \t]*<<" limit t)
  2164.         (setq indent (- (current-column) 2 eif-indent-increment))
  2165.           (re-search-forward "^[ \t]*" limit t)
  2166.           (setq indent (current-column))
  2167.           )
  2168.         )
  2169.     )
  2170.       )
  2171.     indent
  2172.     )
  2173.   )
  2174.  
  2175. ;;; ----------------------------------------------------------------------
  2176. ;;; The function below is derived from "eif-mult-fmt.el"
  2177. ;;; Copyright (C) 1985 Free Software Foundation, Inc.
  2178. ;;; Copyright (C) 1990 Bob Weiner, Motorola Inc.
  2179. ;;; Available for use and distribution under the same terms as GNU Emacs.
  2180. ;;; ----------------------------------------------------------------------
  2181.  
  2182. (defun eif-indent-multi-line (&optional parse-start)
  2183.   "Return integer giving appropriate indentation for current Eiffel code
  2184. line between parentheses or double quotes, otherwise -1.  Optional
  2185. PARSE-START is buffer position at which to begin parsing, default is to begin
  2186. at the feature enclosing or preceding point."
  2187.   (let ((eif-opoint (point))
  2188.     (indent-point (progn (beginning-of-line) (point)))
  2189.     (eif-ind-val -1)
  2190.     (eif-in-str nil)
  2191.     (eif-paren-depth 0)
  2192.     (retry t)
  2193.     state
  2194.     ;; setting this to a number inhibits calling hook
  2195.     last-sexp containing-sexp)
  2196.     (if parse-start
  2197.     (goto-char parse-start)
  2198.       (eif-beginning-of-feature))
  2199.     ;; Find outermost containing sexp
  2200.     (while (< (point) indent-point)
  2201.       (setq state (parse-partial-sexp (point) indent-point 0)))
  2202.     ;; Find innermost containing sexp
  2203.     (while (and retry
  2204.         state
  2205.         (> (setq eif-paren-depth (elt state 0)) 0))
  2206.       (setq retry nil)
  2207.       (setq last-sexp (elt state 2))
  2208.       (setq containing-sexp (elt state 1))
  2209.       ;; Position following last unclosed open.
  2210.       (goto-char (1+ containing-sexp))
  2211.       ;; Is there a complete sexp since then?
  2212.       (if (and last-sexp (> last-sexp (point)))
  2213.       ;; Yes, but is there a containing sexp after that?
  2214.       (let ((peek (parse-partial-sexp last-sexp indent-point 0)))
  2215.         (if (setq retry (car (cdr peek))) (setq state peek)))))
  2216.     (if retry
  2217.     nil
  2218.       ;; Innermost containing sexp found
  2219.       (goto-char (1+ containing-sexp))
  2220.       (if (not last-sexp)
  2221.       ;; indent-point immediately follows open paren.
  2222.       nil
  2223.     ;; Find the start of first element of containing sexp.
  2224.     (parse-partial-sexp (point) last-sexp 0 t)
  2225.     (cond ((looking-at "\\s(")
  2226.            ;; First element of containing sexp is a list.
  2227.            ;; Indent under that list.
  2228.            )
  2229.           ((> (save-excursion (forward-line 1) (point))
  2230.           last-sexp)
  2231.            ;; This is the first line to start within the containing sexp.
  2232.            (backward-prefix-chars))
  2233.           (t
  2234.            ;; Indent beneath first sexp on same line as last-sexp.
  2235.            ;; Again, it's almost certainly a routine call.
  2236.            (goto-char last-sexp)
  2237.            (beginning-of-line)
  2238.            (parse-partial-sexp (point) last-sexp 0 t)
  2239.            (backward-prefix-chars))))
  2240.       (setq eif-ind-val (current-column))
  2241.       )
  2242.     ;; Point is at the point to indent under unless we are inside a string.
  2243.     (setq eif-in-str (elt state 3))
  2244.     (goto-char eif-opoint)
  2245.     (if (not eif-in-str)
  2246.     nil
  2247.       ;; Inside a string, indent 1 past string start
  2248.       (setq eif-paren-depth 1);; To account for being inside string
  2249.       (save-excursion
  2250.     (if (re-search-backward "\"" nil t)
  2251.         (setq eif-ind-val (1+ (current-column)))
  2252.       (goto-char indent-point)
  2253.       (if (looking-at "^[ \t]*[^ \t\n]")
  2254.           (eif-move-to-prev-non-blank))
  2255.       (skip-chars-forward " \t")
  2256.       (setq eif-ind-val (current-column)))))
  2257.     (if (> eif-paren-depth 0) eif-ind-val -1)
  2258.     ))
  2259.  
  2260. (provide 'eiffel3)
  2261.